/* * 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.ospf.controller.impl; import org.onlab.packet.Ip4Address; import org.onlab.util.Bandwidth; import org.onosproject.ospf.controller.DeviceInformation; import org.onosproject.ospf.controller.LinkInformation; import org.onosproject.ospf.controller.OspfArea; import org.onosproject.ospf.controller.OspfInterface; import org.onosproject.ospf.controller.OspfLinkTed; import org.onosproject.ospf.controller.OspfLsa; import org.onosproject.ospf.controller.OspfLsaType; import org.onosproject.ospf.controller.TopologyForDeviceAndLink; import org.onosproject.ospf.protocol.lsa.linksubtype.LinkSubType; import org.onosproject.ospf.protocol.lsa.linksubtype.LocalInterfaceIpAddress; import org.onosproject.ospf.protocol.lsa.linksubtype.MaximumBandwidth; import org.onosproject.ospf.protocol.lsa.linksubtype.MaximumReservableBandwidth; import org.onosproject.ospf.protocol.lsa.linksubtype.RemoteInterfaceIpAddress; import org.onosproject.ospf.protocol.lsa.linksubtype.TrafficEngineeringMetric; import org.onosproject.ospf.protocol.lsa.linksubtype.UnreservedBandwidth; import org.onosproject.ospf.protocol.lsa.subtypes.OspfLsaLink; import org.onosproject.ospf.protocol.lsa.tlvtypes.LinkTlv; import org.onosproject.ospf.protocol.lsa.types.NetworkLsa; import org.onosproject.ospf.protocol.lsa.types.OpaqueLsa10; import org.onosproject.ospf.protocol.lsa.types.RouterLsa; import org.onosproject.ospf.protocol.lsa.types.TopLevelTlv; import org.onosproject.ospf.protocol.util.OspfUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; /** * Represents device and link topology information. */ public class TopologyForDeviceAndLinkImpl implements TopologyForDeviceAndLink { private static final Logger log = LoggerFactory.getLogger(TopologyForDeviceAndLinkImpl.class); Set<Ip4Address> routerSet = new TreeSet<Ip4Address>(); Ip4Address firstValue = Ip4Address.valueOf("0.0.0.0"); private Map<String, DeviceInformation> deviceInformationMap = new LinkedHashMap(); private Map<Ip4Address, List<Ip4Address>> networkLsaMap = new LinkedHashMap(); private Map<String, DeviceInformation> deviceInformationMapForPointToPoint = new LinkedHashMap(); private Map<String, DeviceInformation> deviceInformationMapToDelete = new LinkedHashMap(); private HashMap<String, Set<OspfLsaLink>> deviceAndLinkInformation = new HashMap(); private HashMap<String, OspfLinkTed> ospfLinkTedHashMap = new LinkedHashMap(); private Ip4Address drRouter = Ip4Address.valueOf("0.0.0.0"); private Ip4Address drRouterOld = Ip4Address.valueOf("0.0.0.0"); private Ip4Address adRouterId = Ip4Address.valueOf("0.0.0.0"); private Map<String, LinkInformation> linkInformationMap = new LinkedHashMap(); private Map<String, LinkInformation> linkInformationMapForPointToPoint = new LinkedHashMap(); private List<String> toRemove = new ArrayList<>(); /** * Gets device information. * * @return device information */ public Map<String, DeviceInformation> deviceInformationMap() { return deviceInformationMap; } /** * Sets device information. * * @param key key used to add in map * @param deviceInformationMap device information instance */ public void setDeviceInformationMap(String key, DeviceInformation deviceInformationMap) { if (deviceInformationMap != null) { this.deviceInformationMap.put(key, deviceInformationMap); } } /** * Gets deviceInformation as map for Point-To-Point. * * @return deviceInformationMap */ public Map<String, DeviceInformation> deviceInformationMapForPointToPoint() { return deviceInformationMapForPointToPoint; } /** * Sets deviceInformation as map for Point-To-Point.. * * @param key key to store device information * @param deviceInformationMap device information instance */ public void setDeviceInformationMapForPointToPoint(String key, DeviceInformation deviceInformationMap) { if (deviceInformationMap != null) { this.deviceInformationMapForPointToPoint.put(key, deviceInformationMap); } } /** * Gets deviceInformation as map. * * @return deviceInformationMap to delete from core */ public Map<String, DeviceInformation> deviceInformationMapToDelete() { return deviceInformationMapToDelete; } /** * Sets device information for removal. * * @param key ket used to add in map * @param deviceInformationMapToDelete map from device information to remove */ public void setDeviceInformationMapToDelete(String key, DeviceInformation deviceInformationMapToDelete) { if (deviceInformationMapToDelete != null) { this.deviceInformationMapToDelete.put(key, deviceInformationMapToDelete); } } /** * Removes Device Information. * * @param key ket used to remove from map */ public void removeDeviceInformationMapFromDeleteMap(String key) { removeDeviceInformationMap(key); if (this.deviceInformationMapToDelete.containsKey(key)) { this.deviceInformationMapToDelete.remove(key); } } /** * Gets Device Information. * * @param key key to store in map * @return Device Information */ public DeviceInformation deviceInformation(String key) { DeviceInformation deviceInformation = this.deviceInformationMap.get(key); return deviceInformation; } /** * Removes Device Information from map. * * @param key key used to remove from map */ public void removeDeviceInformationMap(String key) { if (this.deviceInformationMap.containsKey(key)) { this.deviceInformationMap.remove(key); } } /** * Gets link information as map. * * @return link information as map */ public Map<String, LinkInformation> linkInformationMap() { return linkInformationMap; } private LinkInformation getLinkInformation(String key) { LinkInformation linkInformation = this.linkInformationMap.get(key); return linkInformation; } /** * Sets link information in map. * * @param key key used to add in map * @param linkInformationMap link information instance */ public void setLinkInformationMap(String key, LinkInformation linkInformationMap) { if (!this.linkInformationMap.containsKey(key)) { this.linkInformationMap.put(key, linkInformationMap); } } /** * Gets linkInformation as map for PointToPoint. * * @return linkInformationMap */ public Map<String, LinkInformation> linkInformationMapForPointToPoint() { return linkInformationMap; } /** * Sets linkInformation as map for PointToPoint. * * @param key key to store link information * @param linkInformationMap link information instance */ public void setLinkInformationMapForPointToPoint(String key, LinkInformation linkInformationMap) { if (!this.linkInformationMap.containsKey(key)) { this.linkInformationMap.put(key, linkInformationMap); } } /** * Removes Link Information from linkInformationMap. * * @param key key to remove link information */ public void removeLinkInformationMap(String key) { if (this.linkInformationMap.containsKey(key)) { this.linkInformationMap.remove(key); } } /** * Gets OSPF Link TED details from the map. * * @param key key used to retreive from map * @return OSPF link ted instance */ public OspfLinkTed getOspfLinkTedHashMap(String key) { OspfLinkTed ospfLinkTed = ospfLinkTedHashMap.get(key); return ospfLinkTed; } /** * Adds device information to map. * * @param ospfLsa OSPF LSA instance * @param ospfInterface OSPF interface instance * @param ospfArea OSPF area instance */ public void addLocalDevice(OspfLsa ospfLsa, OspfInterface ospfInterface, OspfArea ospfArea) { if (ospfLsa.getOspfLsaType().equals(OspfLsaType.ROUTER)) { createDeviceAndLinkFromRouterLsa(ospfLsa, ospfArea); } else if (ospfLsa.getOspfLsaType().equals(OspfLsaType.NETWORK)) { createDeviceAndLinkFromNetworkLsa(ospfLsa, ospfArea); } else if (ospfLsa.getOspfLsaType().equals(OspfLsaType.AREA_LOCAL_OPAQUE_LSA)) { createDeviceAndLinkFromOpaqueLsa(ospfLsa, ospfArea); } } /** * Creates device object from parameters. * * @param alreadyCreated device already created or not * @param deviceId device id * @param neighborId neighbor's id * @param routerId router's id * @param interfaceId interface id * @param areaId area id * @param isDr true if router is DR else false */ private DeviceInformation createDeviceInformation(boolean alreadyCreated, Ip4Address deviceId, Ip4Address neighborId, Ip4Address routerId, Ip4Address interfaceId, Ip4Address areaId, boolean isDr) { DeviceInformation deviceInformation = new DeviceInformationImpl(); deviceInformation.setAlreadyCreated(alreadyCreated); deviceInformation.setDeviceId(deviceId); deviceInformation.setNeighborId(neighborId); deviceInformation.setRouterId(routerId); deviceInformation.addInterfaceId(interfaceId); deviceInformation.setAreaId(areaId); deviceInformation.setDr(isDr); return deviceInformation; } /** * Creates Device and Link instance from the RouterLsa parameters. * * @param ospfLsa OSPF LSA instance * @param ospfArea OSPF area */ private void createDeviceAndLinkFromRouterLsa(OspfLsa ospfLsa, OspfArea ospfArea) { RouterLsa routerLsa = (RouterLsa) ospfLsa; List<OspfLsaLink> ospfLsaLinkList = routerLsa.routerLink(); Iterator iterator = ospfLsaLinkList.iterator(); Ip4Address advertisingRouterId = routerLsa.advertisingRouter(); while (iterator.hasNext()) { OspfLsaLink ospfLsaLink = (OspfLsaLink) iterator.next(); Ip4Address linkId = Ip4Address.valueOf(ospfLsaLink.linkId()); Ip4Address linkData = Ip4Address.valueOf(ospfLsaLink.linkData()); if (ospfLsaLink.linkType() == 1) { if ((advertisingRouterId.equals(ospfArea.routerId())) || (linkId.equals(ospfArea.routerId()))) { if (!advertisingRouterId.equals(ospfArea.routerId())) { DeviceInformation deviceInformationPointToPoint = createDeviceInformation(false, linkId, linkId, advertisingRouterId, linkData, ospfArea.areaId(), false); String key = "device:" + advertisingRouterId; setDeviceInformationMapForPointToPoint(key, deviceInformationPointToPoint); } } else { DeviceInformation deviceInformationPointToPoint = createDeviceInformation(false, linkId, linkId, advertisingRouterId, linkData, ospfArea.areaId(), false); String key = "device:" + advertisingRouterId; setDeviceInformationMapForPointToPoint(key, deviceInformationPointToPoint); String linkIdKey = "linkId:" + advertisingRouterId + "-" + linkId; addLocalLinkForPointToPoint(linkIdKey, linkData, advertisingRouterId, linkId, true, false); } } } } /** * Creates device and link instance from the network LSA parameters. * * @param ospfLsa OSPF LSA instance * @param ospfArea OSPF area instance */ private void createDeviceAndLinkFromNetworkLsa(OspfLsa ospfLsa, OspfArea ospfArea) { NetworkLsa networkLsa = (NetworkLsa) ospfLsa; Ip4Address linkStateId = Ip4Address.valueOf(networkLsa.linkStateId()); Set<Ip4Address> drList = networkLsaMap.keySet(); try { Ip4Address drToReplace = null; for (Ip4Address drIp : drList) { if (!drIp.equals(linkStateId)) { if (OspfUtil.sameNetwork(drIp, linkStateId, networkLsa.networkMask())) { drToReplace = drIp; String key = "device:" + drToReplace; DeviceInformation deleteDr = deviceInformation(key); if (deleteDr != null) { deleteDr.setAlreadyCreated(true); setDeviceInformationMapToDelete(key, deleteDr); } networkLsaMap.remove(drToReplace); break; } } } networkLsaMap.put(linkStateId, networkLsa.attachedRouters()); } catch (Exception e) { log.debug("Error::TopologyForDeviceAndLinkImpl:: {}", e.getMessage()); } constructDeviceForBroadCastTopology(ospfArea); disp(); } private void constructDeviceForBroadCastTopology(OspfArea ospfArea) { for (Map.Entry<Ip4Address, List<Ip4Address>> entry : networkLsaMap.entrySet()) { Ip4Address key = entry.getKey(); DeviceInformation deviceInformationForDr = createDeviceInformation(false, key, key, key, key, ospfArea.areaId(), true); String dr = "device:" + key; setDeviceInformationMap(dr, deviceInformationForDr); List<Ip4Address> value = entry.getValue(); for (Ip4Address connectedRouter : value) { if (!connectedRouter.equals(ospfArea.routerId())) { DeviceInformation deviceInformationAttachedRouters = createDeviceInformation(false, connectedRouter, key, connectedRouter, key, ospfArea.areaId(), false); String attachedRouters = "device:" + connectedRouter; setDeviceInformationMap(attachedRouters, deviceInformationAttachedRouters); String linkIdKey = "linkId:" + key + "-" + connectedRouter; addLocalLink(linkIdKey, key, key, connectedRouter, true, false); } } } } private void disp() { for (String key : deviceInformationMap.keySet()) { DeviceInformation deviceInformation = deviceInformationMap.get(key); log.debug("************************************************************************"); log.debug("DeviceInfoList RouterId is : {} and neighbour is {} and linkdata {}", deviceInformation.routerId(), deviceInformation.neighborId(), deviceInformation.interfaceId()); } for (Map.Entry<String, LinkInformation> entry : linkInformationMap.entrySet()) { String linkDetail = entry.getKey(); log.debug("Link From and to is " + linkDetail); } log.debug("Devices Needs to delete from Core are : " + deviceInformationMapToDelete.size()); for (String key : deviceInformationMapToDelete.keySet()) { DeviceInformation value = deviceInformationMapToDelete.get(key); if (value.isAlreadyCreated()) { log.debug("Device is deleted from list " + value.routerId()); } } } private void getLinksToDelete(Set<Ip4Address> list, Ip4Address value, OspfArea ospfArea) { Iterator iterator = list.iterator(); while (iterator.hasNext()) { Ip4Address secondValue = (Ip4Address) iterator.next(); if (!value.toString().equals("0.0.0.0")) { if ((!value.equals(secondValue))) { if ((!secondValue.equals(ospfArea.routerId()))) { String key = "link:" + value.toString() + "-" + secondValue.toString(); String key1 = "link:" + secondValue.toString() + "-" + value.toString(); LinkInformation linkDetails = getLinkInformation(key); LinkInformation linkDetailsOther = getLinkInformation(key1); linkInformationMapForPointToPoint.put(key, linkDetails); linkInformationMapForPointToPoint.put(key1, linkDetailsOther); } } } } } /** * Creates Device and Link instance from the OpaqueLsa parameters. * * @param ospfLsa OSPF LSA instance * @param ospfArea OSPF area instance */ private void createDeviceAndLinkFromOpaqueLsa(OspfLsa ospfLsa, OspfArea ospfArea) { OspfLinkTed ospfLinkTed = new OspfLinkTedImpl(); OpaqueLsa10 opaqueLsa10 = (OpaqueLsa10) ospfLsa; List<TopLevelTlv> topLevelTlvList = opaqueLsa10.topLevelValues(); for (TopLevelTlv topLevelTlv : topLevelTlvList) { if (topLevelTlv instanceof LinkTlv) { LinkTlv linkTlv = (LinkTlv) topLevelTlv; List<LinkSubType> subTypes = linkTlv.subTlvList(); for (LinkSubType type : subTypes) { if (type instanceof UnreservedBandwidth) { UnreservedBandwidth unreservedBandwidth = (UnreservedBandwidth) type; List<Float> bandwidthFloatValues = unreservedBandwidth.getUnReservedBandwidthValue(); List<Bandwidth> bandwidthList = new ArrayList<>(); for (Float value : bandwidthFloatValues) { Bandwidth bandwidth = Bandwidth.bps((double) value); ospfLinkTed.setMaxUnResBandwidth(bandwidth); bandwidthList.add(bandwidth); } } if (type instanceof MaximumBandwidth) { MaximumBandwidth maximumBandwidth = (MaximumBandwidth) type; float maxBandValue = maximumBandwidth.getMaximumBandwidthValue(); Bandwidth bandwidth = Bandwidth.bps((double) maxBandValue); ospfLinkTed.setMaximumLink(bandwidth); } if (type instanceof MaximumReservableBandwidth) { MaximumReservableBandwidth maximumReservableBandwidth = (MaximumReservableBandwidth) type; float maxResBandValue = maximumReservableBandwidth.getMaximumBandwidthValue(); Bandwidth bandwidth = Bandwidth.bps((double) maxResBandValue); ospfLinkTed.setMaxReserved(bandwidth); } if (type instanceof TrafficEngineeringMetric) { TrafficEngineeringMetric trafficEngineeringMetric = (TrafficEngineeringMetric) type; long teMetric = trafficEngineeringMetric.getTrafficEngineeringMetricValue(); ospfLinkTed.setTeMetric((Integer) (int) teMetric); } if (type instanceof LocalInterfaceIpAddress) { LocalInterfaceIpAddress localInterfaceIpAddress = (LocalInterfaceIpAddress) type; List<String> stringValue = localInterfaceIpAddress.getLocalInterfaceIPAddress(); List<Ip4Address> localIp4Address = new ArrayList<>(); for (String value : stringValue) { Ip4Address ip4Address = Ip4Address.valueOf(value); localIp4Address.add(ip4Address); } ospfLinkTed.setIpv4LocRouterId(localIp4Address); } if (type instanceof RemoteInterfaceIpAddress) { RemoteInterfaceIpAddress remoteInterfaceIpAddress = (RemoteInterfaceIpAddress) type; List<String> stringValue = remoteInterfaceIpAddress.getRemoteInterfaceAddress(); List<Ip4Address> remoteIp4Address = new ArrayList<>(); for (String value : stringValue) { Ip4Address ip4Address = Ip4Address.valueOf(value); remoteIp4Address.add(ip4Address); } ospfLinkTed.setIpv4RemRouterId(remoteIp4Address); } } } } ospfLinkTedHashMap.put(adRouterId.toString(), ospfLinkTed); } /** * Adds link information to LinkInformationMap. * * @param advertisingRouter advertising router * @param linkData link data address * @param linkSrc link source address * @param linkDest link destination address * @param opaqueEnabled opaque enabled or not * @param linkSrcIdNotRouterId link source id or not */ public void addLocalLink(String advertisingRouter, Ip4Address linkData, Ip4Address linkSrc, Ip4Address linkDest, boolean opaqueEnabled, boolean linkSrcIdNotRouterId) { String linkKey = "link:"; LinkInformation linkInformation = new LinkInformationImpl(); linkInformation.setLinkId(advertisingRouter); linkInformation.setLinkSourceId(linkSrc); linkInformation.setLinkDestinationId(linkDest); linkInformation.setAlreadyCreated(false); linkInformation.setLinkSrcIdNotRouterId(linkSrcIdNotRouterId); linkInformation.setInterfaceIp(linkData); if (linkDest != null) { linkInformation.setLinkSrcIdNotRouterId(false); } linkKey = linkKey + "-" + linkSrc + "-" + linkDest; setLinkInformationMap(linkKey, linkInformation); } /** * Adds link information to LinkInformationMap for PointToPoint. * * @param advertisingRouter advertising router * @param linkData link data * @param linkSrc link source * @param linkDest link destination * @param opaqueEnabled whether opaque is enabled or not * @param linkSrcIdNotRouterId whether link is source id or router id */ public void addLocalLinkForPointToPoint(String advertisingRouter, Ip4Address linkData, Ip4Address linkSrc, Ip4Address linkDest, boolean opaqueEnabled, boolean linkSrcIdNotRouterId) { String linkKey = "link:"; LinkInformation linkInformation = new LinkInformationImpl(); linkInformation.setLinkId(advertisingRouter); linkInformation.setLinkSourceId(linkSrc); linkInformation.setLinkDestinationId(linkDest); linkInformation.setAlreadyCreated(false); linkInformation.setLinkSrcIdNotRouterId(linkSrcIdNotRouterId); linkInformation.setInterfaceIp(linkData); if (linkDest != null) { linkInformation.setLinkSrcIdNotRouterId(false); } linkKey = linkKey + "-" + linkSrc + "-" + linkDest; setLinkInformationMapForPointToPoint(linkKey, linkInformation); } /** * Removes links from LinkInformationMap. * * @param routerId router id */ public void removeLinks(Ip4Address routerId) { Map<String, LinkInformation> linkInformationMapLocal = linkInformationMap; if (linkInformationMapLocal != null) { for (Map.Entry<String, LinkInformation> entry : linkInformationMap.entrySet()) { String key = entry.getKey(); boolean check = key.contains(routerId.toString()); LinkInformation linkInformation = linkInformationMap.get(key); boolean check1 = (linkInformation.linkDestinationId() == routerId) ? true : false; if (check || check1) { toRemove.add(key); } } removeLinkFromMap(); } } /** * Removes Device from DeviceInformationMap. * * @param routerId router id */ public void removeDevice(Ip4Address routerId) { String key = "device:" + routerId; this.deviceInformationMap.remove(key); } /** * Removes link information from Map. */ private void removeLinkFromMap() { Iterator iterator = toRemove.iterator(); while (iterator.hasNext()) { String key = (String) iterator.next(); removeLinkInformationMap(key); } } /** * Updates the deviceAndLinkInformation list for received OSPF LSA. * * @param ospfLsa OSPF LSA instance * @param ospfArea OSPF area instance */ public void updateLinkInformation(OspfLsa ospfLsa, OspfArea ospfArea) { if (ospfLsa.getOspfLsaType().equals(OspfLsaType.ROUTER)) { RouterLsa routerLsa = (RouterLsa) ospfLsa; routerLsa.lsType(); List<OspfLsaLink> ospfLsaLinkList = routerLsa.routerLink(); for (OspfLsaLink link : ospfLsaLinkList) { if (link.linkType() == 1 || link.linkType() == 2) { if ((routerLsa.advertisingRouter().equals(ospfArea.routerId())) || (link.equals(ospfArea.routerId()))) { log.debug("OspfInterface information will not display in web "); } else { String key = routerLsa.advertisingRouter() + "-" + link.linkData(); Set<OspfLsaLink> linkInformations = new HashSet<>(); if (deviceAndLinkInformation.containsKey(key)) { linkInformations = deviceAndLinkInformation.get(key); linkInformations.add(link); deviceAndLinkInformation.put(key, linkInformations); } else { linkInformations.add(link); deviceAndLinkInformation.put(key, linkInformations); } } } } } } /** * Gets all the router information which needs to delete from deviceList. * * @param ospfLsa OSPF LSA instance * @param ospfArea OSPF area instance * @return list of deleted router information */ public List<String> getDeleteRouterInformation(OspfLsa ospfLsa, OspfArea ospfArea) { List<String> removedLinkList = new ArrayList<>(); if (ospfLsa.getOspfLsaType().equals(OspfLsaType.ROUTER)) { RouterLsa routerLsa = (RouterLsa) ospfLsa; List<OspfLsaLink> ospfLsaLinkList = routerLsa.routerLink(); for (OspfLsaLink link : ospfLsaLinkList) { if (link.linkType() == 1 || link.linkType() == 2) { if ((routerLsa.advertisingRouter().equals(ospfArea.routerId())) || (link.equals(ospfArea.routerId()))) { log.debug("OspfInterface information will not display in web "); } else { String key = routerLsa.advertisingRouter() + "-" + link.linkData(); Set<OspfLsaLink> linkInformations = deviceAndLinkInformation.get(key); if (linkInformations.contains(link)) { linkInformations.remove(link); deviceAndLinkInformation.put(key, linkInformations); } } } Set<String> keys = deviceAndLinkInformation.keySet(); for (String key : keys) { Set<OspfLsaLink> linkInformations = deviceAndLinkInformation.get(key); for (OspfLsaLink link1 : linkInformations) { String removedLink = link1.linkId(); removedLinkList.add(removedLink); } } } } return removedLinkList; } }