blob: 4565a4ea38012d33deb0187cfa2d5871c1b400a0 [file] [log] [blame]
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -08003 *
Simon Hunted804d52016-03-30 09:51:40 -07004 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -08007 *
Simon Hunted804d52016-03-30 09:51:40 -07008 * http://www.apache.org/licenses/LICENSE-2.0
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -08009 *
Simon Hunted804d52016-03-30 09:51:40 -070010 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -080015 */
Simon Hunted804d52016-03-30 09:51:40 -070016package org.onosproject.ui.impl.topo.util;
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -080017
Brian O'Connorabafb502014-12-02 22:26:20 -080018import org.onosproject.net.ConnectPoint;
19import org.onosproject.net.Device;
20import org.onosproject.net.DeviceId;
21import org.onosproject.net.Host;
22import org.onosproject.net.HostId;
23import org.onosproject.net.Link;
Thomas Vachuska48958b12015-06-10 10:54:53 -070024import org.onosproject.net.flow.FlowRule;
Thomas Vachuskada0665b2016-03-02 19:06:17 -080025import org.onosproject.net.intent.FlowObjectiveIntent;
Thomas Vachuska48958b12015-06-10 10:54:53 -070026import org.onosproject.net.intent.FlowRuleIntent;
Brian O'Connorabafb502014-12-02 22:26:20 -080027import org.onosproject.net.intent.HostToHostIntent;
28import org.onosproject.net.intent.Intent;
29import org.onosproject.net.intent.IntentService;
30import org.onosproject.net.intent.LinkCollectionIntent;
31import org.onosproject.net.intent.MultiPointToSinglePointIntent;
32import org.onosproject.net.intent.OpticalConnectivityIntent;
33import org.onosproject.net.intent.PathIntent;
34import org.onosproject.net.intent.PointToPointIntent;
35import org.onosproject.net.link.LinkService;
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -080036
Thomas Vachuska164fa5c2014-12-02 21:59:41 -080037import java.util.ArrayList;
Thomas Vachuska48958b12015-06-10 10:54:53 -070038import java.util.Collection;
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -080039import java.util.HashSet;
40import java.util.List;
Thomas Vachuska48958b12015-06-10 10:54:53 -070041import java.util.Objects;
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -080042import java.util.Set;
43
Brian O'Connorabafb502014-12-02 22:26:20 -080044import static org.onosproject.net.intent.IntentState.INSTALLED;
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -080045
46/**
47 * Auxiliary facility to query the intent service based on the specified
48 * set of end-station hosts, edge points or infrastructure devices.
49 */
Simon Hunt4fc86852015-08-20 17:57:52 -070050public class TopoIntentFilter {
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -080051
52 private final IntentService intentService;
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -080053 private final LinkService linkService;
54
55 /**
Simon Hunta17fa672015-08-19 18:42:22 -070056 * Creates an intent filter.
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -080057 *
Simon Hunta17fa672015-08-19 18:42:22 -070058 * @param services service references bundle
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -080059 */
Simon Hunt4fc86852015-08-20 17:57:52 -070060 public TopoIntentFilter(ServicesBundle services) {
Simon Hunt1911fe42017-05-02 18:25:58 -070061 this.intentService = services.intent();
62 this.linkService = services.link();
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -080063 }
64
65 /**
Simon Hunta17fa672015-08-19 18:42:22 -070066 * Finds all path (host-to-host or point-to-point) intents that pertain
67 * to the given hosts and devices.
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -080068 *
Simon Hunt1911fe42017-05-02 18:25:58 -070069 * @param hosts set of hosts to query by
70 * @param devices set of devices to query by
71 * @param links set of links to query by
Prince Pereira46c82d42016-09-19 13:30:50 +053072 * @return set of intents that 'match' all hosts, devices and links given
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -080073 */
Prince Pereira46c82d42016-09-19 13:30:50 +053074 public List<Intent> findPathIntents(Set<Host> hosts,
75 Set<Device> devices,
76 Set<Link> links) {
Simon Hunta17fa672015-08-19 18:42:22 -070077 // start with all intents
78 Iterable<Intent> sourceIntents = intentService.getIntents();
79
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -080080 // Derive from this the set of edge connect points.
81 Set<ConnectPoint> edgePoints = getEdgePoints(hosts);
82
83 // Iterate over all intents and produce a set that contains only those
84 // intents that target all selected hosts or derived edge connect points.
Prince Pereira46c82d42016-09-19 13:30:50 +053085 return getIntents(hosts, devices, links, edgePoints, sourceIntents);
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -080086 }
87
88
89 // Produces a set of edge points from the specified set of hosts.
90 private Set<ConnectPoint> getEdgePoints(Set<Host> hosts) {
91 Set<ConnectPoint> edgePoints = new HashSet<>();
92 for (Host host : hosts) {
93 edgePoints.add(host.location());
94 }
95 return edgePoints;
96 }
97
Prince Pereira46c82d42016-09-19 13:30:50 +053098 // Produces a list of intents that target all selected hosts, devices, links or connect points.
99 private List<Intent> getIntents(Set<Host> hosts, Set<Device> devices, Set<Link> links,
Thomas Vachuska164fa5c2014-12-02 21:59:41 -0800100 Set<ConnectPoint> edgePoints,
101 Iterable<Intent> sourceIntents) {
102 List<Intent> intents = new ArrayList<>();
Prince Pereira46c82d42016-09-19 13:30:50 +0530103 if (hosts.isEmpty() && devices.isEmpty() && links.isEmpty()) {
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800104 return intents;
105 }
106
107 Set<OpticalConnectivityIntent> opticalIntents = new HashSet<>();
108
109 // Search through all intents and see if they are relevant to our search.
Thomas Vachuska164fa5c2014-12-02 21:59:41 -0800110 for (Intent intent : sourceIntents) {
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800111 if (intentService.getIntentState(intent.key()) == INSTALLED) {
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800112 boolean isRelevant = false;
113 if (intent instanceof HostToHostIntent) {
114 isRelevant = isIntentRelevantToHosts((HostToHostIntent) intent, hosts) &&
Prince Pereira46c82d42016-09-19 13:30:50 +0530115 isIntentRelevantToDevices(intent, devices) && isIntentRelevantToLinks(intent, links);
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800116 } else if (intent instanceof PointToPointIntent) {
117 isRelevant = isIntentRelevant((PointToPointIntent) intent, edgePoints) &&
Prince Pereira46c82d42016-09-19 13:30:50 +0530118 isIntentRelevantToDevices(intent, devices) && isIntentRelevantToLinks(intent, links);
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800119 } else if (intent instanceof MultiPointToSinglePointIntent) {
120 isRelevant = isIntentRelevant((MultiPointToSinglePointIntent) intent, edgePoints) &&
Prince Pereira46c82d42016-09-19 13:30:50 +0530121 isIntentRelevantToDevices(intent, devices) && isIntentRelevantToLinks(intent, links);
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800122 } else if (intent instanceof OpticalConnectivityIntent) {
123 opticalIntents.add((OpticalConnectivityIntent) intent);
124 }
125 // TODO: add other intents, e.g. SinglePointToMultiPointIntent
126
127 if (isRelevant) {
128 intents.add(intent);
129 }
130 }
131 }
132
133 // As a second pass, try to link up any optical intents with the
134 // packet-level ones.
135 for (OpticalConnectivityIntent intent : opticalIntents) {
136 if (isIntentRelevant(intent, intents) &&
137 isIntentRelevantToDevices(intent, devices)) {
138 intents.add(intent);
139 }
140 }
141 return intents;
142 }
143
144 // Indicates whether the specified intent involves all of the given hosts.
Thomas Vachuska164fa5c2014-12-02 21:59:41 -0800145 private boolean isIntentRelevantToHosts(HostToHostIntent intent, Iterable<Host> hosts) {
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800146 for (Host host : hosts) {
147 HostId id = host.id();
148 // Bail if intent does not involve this host.
149 if (!id.equals(intent.one()) && !id.equals(intent.two())) {
150 return false;
151 }
152 }
153 return true;
154 }
155
156 // Indicates whether the specified intent involves all of the given devices.
Thomas Vachuska164fa5c2014-12-02 21:59:41 -0800157 private boolean isIntentRelevantToDevices(Intent intent, Iterable<Device> devices) {
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800158 List<Intent> installables = intentService.getInstallableIntents(intent.key());
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800159 for (Device device : devices) {
160 if (!isIntentRelevantToDevice(installables, device)) {
161 return false;
162 }
163 }
164 return true;
165 }
166
Prince Pereira46c82d42016-09-19 13:30:50 +0530167 // Indicates whether the specified intent involves all of the given links.
168 private boolean isIntentRelevantToLinks(Intent intent, Iterable<Link> links) {
169 List<Intent> installables = intentService.getInstallableIntents(intent.key());
170 for (Link link : links) {
171 if (!isIntentRelevantToLink(installables, link)) {
172 return false;
173 }
174 }
175 return true;
176 }
177
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800178 // Indicates whether the specified intent involves the given device.
179 private boolean isIntentRelevantToDevice(List<Intent> installables, Device device) {
Thomas Vachuska4731f122014-11-20 04:56:19 -0800180 if (installables != null) {
181 for (Intent installable : installables) {
182 if (installable instanceof PathIntent) {
183 PathIntent pathIntent = (PathIntent) installable;
184 if (pathContainsDevice(pathIntent.path().links(), device.id())) {
185 return true;
186 }
Thomas Vachuska48958b12015-06-10 10:54:53 -0700187 } else if (installable instanceof FlowRuleIntent) {
188 FlowRuleIntent flowRuleIntent = (FlowRuleIntent) installable;
189 if (rulesContainDevice(flowRuleIntent.flowRules(), device.id())) {
190 return true;
191 }
Thomas Vachuskada0665b2016-03-02 19:06:17 -0800192 } else if (installable instanceof FlowObjectiveIntent) {
193 FlowObjectiveIntent objectiveIntent = (FlowObjectiveIntent) installable;
194 return objectiveIntent.devices().contains(device.id());
195
Thomas Vachuska4731f122014-11-20 04:56:19 -0800196 } else if (installable instanceof LinkCollectionIntent) {
197 LinkCollectionIntent linksIntent = (LinkCollectionIntent) installable;
198 if (pathContainsDevice(linksIntent.links(), device.id())) {
199 return true;
200 }
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800201 }
202 }
203 }
204 return false;
205 }
206
Prince Pereira46c82d42016-09-19 13:30:50 +0530207 // Indicates whether the specified intent involves the given link.
208 private boolean isIntentRelevantToLink(List<Intent> installables, Link link) {
209 Link reverseLink = linkService.getLink(link.dst(), link.src());
210
211 if (installables != null) {
212 for (Intent installable : installables) {
213 if (installable instanceof PathIntent) {
214 PathIntent pathIntent = (PathIntent) installable;
215 return pathIntent.path().links().contains(link) ||
216 pathIntent.path().links().contains(reverseLink);
217
218 } else if (installable instanceof FlowRuleIntent) {
219 FlowRuleIntent flowRuleIntent = (FlowRuleIntent) installable;
220 return flowRuleIntent.resources().contains(link) ||
221 flowRuleIntent.resources().contains(reverseLink);
222
223 } else if (installable instanceof FlowObjectiveIntent) {
224 FlowObjectiveIntent objectiveIntent = (FlowObjectiveIntent) installable;
225 return objectiveIntent.resources().contains(link) ||
226 objectiveIntent.resources().contains(reverseLink);
227
228 } else if (installable instanceof LinkCollectionIntent) {
229 LinkCollectionIntent linksIntent = (LinkCollectionIntent) installable;
230 return linksIntent.links().contains(link) ||
231 linksIntent.links().contains(reverseLink);
232
233 }
234 }
235 }
236 return false;
237 }
238
Thomas Vachuska48958b12015-06-10 10:54:53 -0700239 // Indicates whether the specified links involve the given device.
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800240 private boolean pathContainsDevice(Iterable<Link> links, DeviceId id) {
241 for (Link link : links) {
242 if (link.src().elementId().equals(id) || link.dst().elementId().equals(id)) {
243 return true;
244 }
245 }
246 return false;
247 }
248
Simon Hunt441c9ae2017-02-03 18:22:31 -0800249 // Indicates whether the specified flow rules involves the given device.
Thomas Vachuska48958b12015-06-10 10:54:53 -0700250 private boolean rulesContainDevice(Collection<FlowRule> flowRules, DeviceId id) {
251 for (FlowRule rule : flowRules) {
252 if (rule.deviceId().equals(id)) {
253 return true;
254 }
255 }
256 return false;
257 }
258
Thomas Vachuska164fa5c2014-12-02 21:59:41 -0800259 private boolean isIntentRelevant(PointToPointIntent intent,
260 Iterable<ConnectPoint> edgePoints) {
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800261 for (ConnectPoint point : edgePoints) {
262 // Bail if intent does not involve this edge point.
Ray Milkeya2cf3a12018-02-15 16:13:56 -0800263 if (!point.equals(intent.filteredEgressPoint().connectPoint()) &&
264 !point.equals(intent.filteredIngressPoint().connectPoint())) {
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800265 return false;
266 }
267 }
268 return true;
269 }
270
271 // Indicates whether the specified intent involves all of the given edge points.
272 private boolean isIntentRelevant(MultiPointToSinglePointIntent intent,
Thomas Vachuska164fa5c2014-12-02 21:59:41 -0800273 Iterable<ConnectPoint> edgePoints) {
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800274 for (ConnectPoint point : edgePoints) {
275 // Bail if intent does not involve this edge point.
276 if (!point.equals(intent.egressPoint()) &&
277 !intent.ingressPoints().contains(point)) {
278 return false;
279 }
280 }
281 return true;
282 }
283
284 // Indicates whether the specified intent involves all of the given edge points.
285 private boolean isIntentRelevant(OpticalConnectivityIntent opticalIntent,
Thomas Vachuska164fa5c2014-12-02 21:59:41 -0800286 Iterable<Intent> intents) {
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800287 Link ccSrc = getFirstLink(opticalIntent.getSrc(), false);
288 Link ccDst = getFirstLink(opticalIntent.getDst(), true);
Thomas Vachuska48958b12015-06-10 10:54:53 -0700289 if (ccSrc == null || ccDst == null) {
290 return false;
291 }
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800292
293 for (Intent intent : intents) {
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800294 List<Intent> installables = intentService.getInstallableIntents(intent.key());
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800295 for (Intent installable : installables) {
296 if (installable instanceof PathIntent) {
297 List<Link> links = ((PathIntent) installable).path().links();
298 if (links.size() == 3) {
299 Link tunnel = links.get(1);
Thomas Vachuska48958b12015-06-10 10:54:53 -0700300 if (Objects.equals(tunnel.src(), ccSrc.src()) &&
301 Objects.equals(tunnel.dst(), ccDst.dst())) {
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800302 return true;
303 }
304 }
305 }
306 }
307 }
308 return false;
309 }
310
311 private Link getFirstLink(ConnectPoint point, boolean ingress) {
312 for (Link link : linkService.getLinks(point)) {
313 if (point.equals(ingress ? link.src() : link.dst())) {
314 return link;
315 }
316 }
317 return null;
318 }
Thomas Vachuska5fedb7a2014-11-20 00:55:08 -0800319}