/* * Copyright 2014-2015 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.ui.impl.topo; import org.onosproject.net.ConnectPoint; import org.onosproject.net.Device; import org.onosproject.net.DeviceId; import org.onosproject.net.Host; import org.onosproject.net.HostId; import org.onosproject.net.Link; import org.onosproject.net.device.DeviceService; import org.onosproject.net.flow.FlowRule; import org.onosproject.net.host.HostService; import org.onosproject.net.intent.FlowRuleIntent; import org.onosproject.net.intent.HostToHostIntent; import org.onosproject.net.intent.Intent; import org.onosproject.net.intent.IntentService; import org.onosproject.net.intent.LinkCollectionIntent; import org.onosproject.net.intent.MultiPointToSinglePointIntent; import org.onosproject.net.intent.OpticalConnectivityIntent; import org.onosproject.net.intent.PathIntent; import org.onosproject.net.intent.PointToPointIntent; import org.onosproject.net.link.LinkService; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; import static org.onosproject.net.intent.IntentState.INSTALLED; /** * Auxiliary facility to query the intent service based on the specified * set of end-station hosts, edge points or infrastructure devices. */ public class TopoIntentFilter { private final IntentService intentService; private final DeviceService deviceService; private final HostService hostService; private final LinkService linkService; /** * Creates an intent filter. * * @param services service references bundle */ public TopoIntentFilter(ServicesBundle services) { this.intentService = services.intentService(); this.deviceService = services.deviceService(); this.hostService = services.hostService(); this.linkService = services.linkService(); } /** * Finds all path (host-to-host or point-to-point) intents that pertain * to the given hosts and devices. * * @param hosts set of hosts to query by * @param devices set of devices to query by * @return set of intents that 'match' all hosts and devices given */ public List findPathIntents(Set hosts, Set devices) { // start with all intents Iterable sourceIntents = intentService.getIntents(); // Derive from this the set of edge connect points. Set edgePoints = getEdgePoints(hosts); // Iterate over all intents and produce a set that contains only those // intents that target all selected hosts or derived edge connect points. return getIntents(hosts, devices, edgePoints, sourceIntents); } // Produces a set of edge points from the specified set of hosts. private Set getEdgePoints(Set hosts) { Set edgePoints = new HashSet<>(); for (Host host : hosts) { edgePoints.add(host.location()); } return edgePoints; } // Produces a list of intents that target all selected hosts, devices or connect points. private List getIntents(Set hosts, Set devices, Set edgePoints, Iterable sourceIntents) { List intents = new ArrayList<>(); if (hosts.isEmpty() && devices.isEmpty()) { return intents; } Set opticalIntents = new HashSet<>(); // Search through all intents and see if they are relevant to our search. for (Intent intent : sourceIntents) { if (intentService.getIntentState(intent.key()) == INSTALLED) { boolean isRelevant = false; if (intent instanceof HostToHostIntent) { isRelevant = isIntentRelevantToHosts((HostToHostIntent) intent, hosts) && isIntentRelevantToDevices(intent, devices); } else if (intent instanceof PointToPointIntent) { isRelevant = isIntentRelevant((PointToPointIntent) intent, edgePoints) && isIntentRelevantToDevices(intent, devices); } else if (intent instanceof MultiPointToSinglePointIntent) { isRelevant = isIntentRelevant((MultiPointToSinglePointIntent) intent, edgePoints) && isIntentRelevantToDevices(intent, devices); } else if (intent instanceof OpticalConnectivityIntent) { opticalIntents.add((OpticalConnectivityIntent) intent); } // TODO: add other intents, e.g. SinglePointToMultiPointIntent if (isRelevant) { intents.add(intent); } } } // As a second pass, try to link up any optical intents with the // packet-level ones. for (OpticalConnectivityIntent intent : opticalIntents) { if (isIntentRelevant(intent, intents) && isIntentRelevantToDevices(intent, devices)) { intents.add(intent); } } return intents; } // Indicates whether the specified intent involves all of the given hosts. private boolean isIntentRelevantToHosts(HostToHostIntent intent, Iterable hosts) { for (Host host : hosts) { HostId id = host.id(); // Bail if intent does not involve this host. if (!id.equals(intent.one()) && !id.equals(intent.two())) { return false; } } return true; } // Indicates whether the specified intent involves all of the given devices. private boolean isIntentRelevantToDevices(Intent intent, Iterable devices) { List installables = intentService.getInstallableIntents(intent.key()); for (Device device : devices) { if (!isIntentRelevantToDevice(installables, device)) { return false; } } return true; } // Indicates whether the specified intent involves the given device. private boolean isIntentRelevantToDevice(List installables, Device device) { if (installables != null) { for (Intent installable : installables) { if (installable instanceof PathIntent) { PathIntent pathIntent = (PathIntent) installable; if (pathContainsDevice(pathIntent.path().links(), device.id())) { return true; } } else if (installable instanceof FlowRuleIntent) { FlowRuleIntent flowRuleIntent = (FlowRuleIntent) installable; if (rulesContainDevice(flowRuleIntent.flowRules(), device.id())) { return true; } } else if (installable instanceof LinkCollectionIntent) { LinkCollectionIntent linksIntent = (LinkCollectionIntent) installable; if (pathContainsDevice(linksIntent.links(), device.id())) { return true; } } } } return false; } // Indicates whether the specified links involve the given device. private boolean pathContainsDevice(Iterable links, DeviceId id) { for (Link link : links) { if (link.src().elementId().equals(id) || link.dst().elementId().equals(id)) { return true; } } return false; } // Indicates whether the specified flow rules involvesthe given device. private boolean rulesContainDevice(Collection flowRules, DeviceId id) { for (FlowRule rule : flowRules) { if (rule.deviceId().equals(id)) { return true; } } return false; } private boolean isIntentRelevant(PointToPointIntent intent, Iterable edgePoints) { for (ConnectPoint point : edgePoints) { // Bail if intent does not involve this edge point. if (!point.equals(intent.egressPoint()) && !point.equals(intent.ingressPoint())) { return false; } } return true; } // Indicates whether the specified intent involves all of the given edge points. private boolean isIntentRelevant(MultiPointToSinglePointIntent intent, Iterable edgePoints) { for (ConnectPoint point : edgePoints) { // Bail if intent does not involve this edge point. if (!point.equals(intent.egressPoint()) && !intent.ingressPoints().contains(point)) { return false; } } return true; } // Indicates whether the specified intent involves all of the given edge points. private boolean isIntentRelevant(OpticalConnectivityIntent opticalIntent, Iterable intents) { Link ccSrc = getFirstLink(opticalIntent.getSrc(), false); Link ccDst = getFirstLink(opticalIntent.getDst(), true); if (ccSrc == null || ccDst == null) { return false; } for (Intent intent : intents) { List installables = intentService.getInstallableIntents(intent.key()); for (Intent installable : installables) { if (installable instanceof PathIntent) { List links = ((PathIntent) installable).path().links(); if (links.size() == 3) { Link tunnel = links.get(1); if (Objects.equals(tunnel.src(), ccSrc.src()) && Objects.equals(tunnel.dst(), ccDst.dst())) { return true; } } } } } return false; } private Link getFirstLink(ConnectPoint point, boolean ingress) { for (Link link : linkService.getLinks(point)) { if (point.equals(ingress ? link.src() : link.dst())) { return link; } } return null; } }