blob: 6b50731710c6522055ce71ea456c0d0c48eab781 [file] [log] [blame]
Yi Tsengf4e13e32017-03-30 15:38:39 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Yi Tsengf4e13e32017-03-30 15:38:39 -07003 *
4 * 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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * 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.
15 */
16package org.onosproject.vpls.intent;
17
18import com.google.common.collect.ImmutableList;
19import com.google.common.collect.ImmutableSet;
20import com.google.common.collect.Sets;
21import org.onlab.packet.MacAddress;
22import org.onlab.packet.VlanId;
23import org.onosproject.core.ApplicationId;
Ray Milkeyfacf2862017-08-03 11:58:29 -070024import org.onosproject.net.intf.Interface;
Yi Tsengf4e13e32017-03-30 15:38:39 -070025import org.onosproject.net.ConnectPoint;
26import org.onosproject.net.EncapsulationType;
27import org.onosproject.net.FilteredConnectPoint;
28import org.onosproject.net.Host;
29import org.onosproject.net.ResourceGroup;
30import org.onosproject.net.flow.DefaultTrafficSelector;
31import org.onosproject.net.flow.TrafficSelector;
32import org.onosproject.net.intent.ConnectivityIntent;
33import org.onosproject.net.intent.Constraint;
34import org.onosproject.net.intent.Intent;
35import org.onosproject.net.intent.Key;
36import org.onosproject.net.intent.MultiPointToSinglePointIntent;
37import org.onosproject.net.intent.SinglePointToMultiPointIntent;
38import org.onosproject.net.intent.constraint.EncapsulationConstraint;
39import org.onosproject.net.intent.constraint.PartialFailureConstraint;
40import org.onosproject.vpls.api.VplsData;
41import org.slf4j.Logger;
42import org.slf4j.LoggerFactory;
43
44import java.util.ArrayList;
45import java.util.List;
46import java.util.Objects;
47import java.util.Set;
48import java.util.stream.Collectors;
49
50import static java.util.Objects.*;
51import static org.onosproject.net.EncapsulationType.*;
52
53/**
54 * Intent utilities for VPLS.
55 */
56public final class VplsIntentUtility {
57 private static final String SP2MP =
58 "Building sp2mp intent from {}";
59 private static final String MP2SP =
60 "Building mp2sp intent to {}";
61
62 private static final Logger log = LoggerFactory.getLogger(
63 VplsIntentUtility.class);
64
65 private static final int PRIORITY_OFFSET = 1000;
66 private static final int PRIORITY_UNI = 200;
67 private static final int PRIORITY_BRC = 100;
68
69 public static final String PREFIX_BROADCAST = "brc";
70 public static final String PREFIX_UNICAST = "uni";
71 private static final String SEPARATOR = "-";
72
73 public static final ImmutableList<Constraint> PARTIAL_FAILURE_CONSTRAINT =
74 ImmutableList.of(new PartialFailureConstraint());
75
76 private VplsIntentUtility() {
77 // Utility classes should not have a public or default constructor.
78 }
79
80 /**
81 * Builds broadcast Intents for a VPLS.
82 *
83 * @param vplsData the VPLS
84 * @param appId the application id for Intents
85 * @return broadcast Intents for the VPLS
86 */
87 public static Set<Intent> buildBrcIntents(VplsData vplsData, ApplicationId appId) {
88 Set<Interface> interfaces = vplsData.interfaces();
89
90 // At least two or more network interfaces to build broadcast Intents
91 if (interfaces.size() < 2) {
92 return ImmutableSet.of();
93 }
94 Set<Intent> brcIntents = Sets.newHashSet();
95 ResourceGroup resourceGroup = ResourceGroup.of(vplsData.name());
96
97 // Generates broadcast Intents from any network interface to other
98 // network interface from the VPLS.
99 interfaces.forEach(src -> {
100 FilteredConnectPoint srcFcp = VplsIntentUtility.buildFilteredConnectedPoint(src);
101 Set<FilteredConnectPoint> dstFcps =
102 interfaces.stream()
103 .filter(iface -> !iface.equals(src))
104 .map(VplsIntentUtility::buildFilteredConnectedPoint)
105 .collect(Collectors.toSet());
106 Key key = VplsIntentUtility.buildKey(PREFIX_BROADCAST,
107 srcFcp.connectPoint(),
108 vplsData.name(),
109 MacAddress.BROADCAST,
110 appId);
111 Intent brcIntent = buildBrcIntent(key,
112 appId,
113 srcFcp,
114 dstFcps,
115 vplsData.encapsulationType(),
116 resourceGroup);
117
118 brcIntents.add(brcIntent);
119 });
120 return brcIntents;
121 }
122
123 /**
124 * Builds a broadcast intent.
125 *
126 * @param key key to identify the intent
127 * @param appId application ID for this Intent
128 * @param src the source connect point
129 * @param dsts the destination connect points
130 * @param encap the encapsulation type
131 * @param resourceGroup resource group for this Intent
132 * @return the generated single-point to multi-point intent
133 */
Ray Milkey9c9cde42018-01-12 14:22:06 -0800134 static SinglePointToMultiPointIntent buildBrcIntent(Key key,
Yi Tsengf4e13e32017-03-30 15:38:39 -0700135 ApplicationId appId,
136 FilteredConnectPoint src,
137 Set<FilteredConnectPoint> dsts,
138 EncapsulationType encap,
139 ResourceGroup resourceGroup) {
140 log.debug("Building broadcast intent {} for source {}", SP2MP, src);
141
142 SinglePointToMultiPointIntent.Builder intentBuilder;
143
144 TrafficSelector selector = DefaultTrafficSelector.builder()
145 .matchEthDst(MacAddress.BROADCAST)
146 .build();
147
148 intentBuilder = SinglePointToMultiPointIntent.builder()
149 .appId(appId)
150 .key(key)
151 .selector(selector)
152 .filteredIngressPoint(src)
153 .filteredEgressPoints(dsts)
154 .constraints(PARTIAL_FAILURE_CONSTRAINT)
155 .priority(PRIORITY_OFFSET + PRIORITY_BRC)
156 .resourceGroup(resourceGroup);
157
158 setEncap(intentBuilder, PARTIAL_FAILURE_CONSTRAINT, encap);
159
160 return intentBuilder.build();
161 }
162
163 /**
164 * Builds unicast Intents for a VPLS.
165 *
166 * @param vplsData the VPLS
167 * @param hosts the hosts of the VPLS
168 * @param appId application ID for Intents
169 * @return unicast Intents for the VPLS
170 */
171 public static Set<Intent> buildUniIntents(VplsData vplsData, Set<Host> hosts, ApplicationId appId) {
172 Set<Interface> interfaces = vplsData.interfaces();
173 if (interfaces.size() < 2) {
174 return ImmutableSet.of();
175 }
176 Set<Intent> uniIntents = Sets.newHashSet();
177 ResourceGroup resourceGroup = ResourceGroup.of(vplsData.name());
178 hosts.forEach(host -> {
179 FilteredConnectPoint hostFcp = buildFilteredConnectedPoint(host);
180 Set<FilteredConnectPoint> srcFcps =
181 interfaces.stream()
182 .map(VplsIntentUtility::buildFilteredConnectedPoint)
183 .filter(fcp -> !fcp.equals(hostFcp))
184 .collect(Collectors.toSet());
185 Key key = buildKey(PREFIX_UNICAST,
186 hostFcp.connectPoint(),
187 vplsData.name(),
188 host.mac(),
189 appId);
190 Intent uniIntent = buildUniIntent(key,
191 appId,
192 srcFcps,
193 hostFcp,
194 host,
195 vplsData.encapsulationType(),
196 resourceGroup);
197 uniIntents.add(uniIntent);
198 });
199
200 return uniIntents;
201 }
202
203 /**
204 * Builds a unicast intent.
205 *
206 * @param key key to identify the intent
207 * @param appId application ID for this Intent
208 * @param srcs the source Connect Points
209 * @param dst the destination Connect Point
210 * @param host destination Host
211 * @param encap the encapsulation type
212 * @param resourceGroup resource group for this Intent
213 * @return the generated multi-point to single-point intent
214 */
Ray Milkey9c9cde42018-01-12 14:22:06 -0800215 static MultiPointToSinglePointIntent buildUniIntent(Key key,
Yi Tsengf4e13e32017-03-30 15:38:39 -0700216 ApplicationId appId,
217 Set<FilteredConnectPoint> srcs,
218 FilteredConnectPoint dst,
219 Host host,
220 EncapsulationType encap,
221 ResourceGroup resourceGroup) {
222 log.debug("Building unicast intent {} for destination {}", MP2SP, dst);
223
224 MultiPointToSinglePointIntent.Builder intentBuilder;
225
226 TrafficSelector selector = DefaultTrafficSelector.builder()
227 .matchEthDst(host.mac())
228 .build();
229
230 intentBuilder = MultiPointToSinglePointIntent.builder()
231 .appId(appId)
232 .key(key)
233 .selector(selector)
234 .filteredIngressPoints(srcs)
235 .filteredEgressPoint(dst)
236 .constraints(PARTIAL_FAILURE_CONSTRAINT)
237 .priority(PRIORITY_OFFSET + PRIORITY_UNI)
238 .resourceGroup(resourceGroup);
239
240 setEncap(intentBuilder, PARTIAL_FAILURE_CONSTRAINT, encap);
241
242 return intentBuilder.build();
243 }
244
245 /**
246 * Builds an intent key either for single-point to multi-point or
247 * multi-point to single-point intents, based on a prefix that defines
248 * the type of intent, the single connect point representing the single
249 * source or destination for that intent, the name of the VPLS the intent
250 * belongs to, and the destination host MAC address the intent reaches.
251 *
252 * @param prefix the key prefix
253 * @param cPoint the connect point identifying the source/destination
254 * @param vplsName the name of the VPLS
255 * @param hostMac the source/destination MAC address
256 * @param appId application ID for the key
257 * @return the key to identify the intent
258 */
Ray Milkey9c9cde42018-01-12 14:22:06 -0800259 static Key buildKey(String prefix,
Yi Tsengf4e13e32017-03-30 15:38:39 -0700260 ConnectPoint cPoint,
261 String vplsName,
262 MacAddress hostMac,
263 ApplicationId appId) {
264 String keyString = vplsName +
265 SEPARATOR +
266 prefix +
267 SEPARATOR +
268 cPoint.deviceId() +
269 SEPARATOR +
270 cPoint.port() +
271 SEPARATOR +
272 hostMac;
273
274 return Key.of(keyString, appId);
275 }
276
277
278 /**
279 * Sets one or more encapsulation constraints on the intent builder given.
280 *
281 * @param builder the intent builder
282 * @param constraints the existing intent constraints
283 * @param encap the encapsulation type to be set
284 */
285 public static void setEncap(ConnectivityIntent.Builder builder,
286 List<Constraint> constraints,
287 EncapsulationType encap) {
288 // Constraints might be an immutable list, so a new modifiable list
289 // is created
290 List<Constraint> newConstraints = new ArrayList<>(constraints);
291
292 // Remove any encapsulation constraint if already in the list
293 constraints.stream()
294 .filter(c -> c instanceof EncapsulationConstraint)
295 .forEach(newConstraints::remove);
296
297 // if the new encapsulation is different from NONE, a new encapsulation
298 // constraint should be added to the list
299 if (!encap.equals(NONE)) {
300 newConstraints.add(new EncapsulationConstraint(encap));
301 }
302
303 // Submit new constraint list as immutable list
304 builder.constraints(ImmutableList.copyOf(newConstraints));
305 }
306
307 /**
308 * Builds filtered connected point by a given network interface.
309 *
310 * @param iface the network interface
311 * @return the filtered connected point of a given network interface
312 */
Ray Milkey9c9cde42018-01-12 14:22:06 -0800313 static FilteredConnectPoint buildFilteredConnectedPoint(Interface iface) {
Yi Tsengf4e13e32017-03-30 15:38:39 -0700314 Objects.requireNonNull(iface);
315 TrafficSelector.Builder trafficSelector = DefaultTrafficSelector.builder();
316
317 if (iface.vlan() != null && !iface.vlan().equals(VlanId.NONE)) {
318 trafficSelector.matchVlanId(iface.vlan());
319 }
320
321 return new FilteredConnectPoint(iface.connectPoint(), trafficSelector.build());
322 }
323
324 /**
325 * Builds filtered connected point by a given host.
326 *
327 * @param host the host
328 * @return the filtered connected point of the given host
329 */
Ray Milkey9c9cde42018-01-12 14:22:06 -0800330 static FilteredConnectPoint buildFilteredConnectedPoint(Host host) {
Yi Tsengf4e13e32017-03-30 15:38:39 -0700331 requireNonNull(host);
332 TrafficSelector.Builder trafficSelector = DefaultTrafficSelector.builder();
333
334 if (host.vlan() != null && !host.vlan().equals(VlanId.NONE)) {
335 trafficSelector.matchVlanId(host.vlan());
336 }
337 return new FilteredConnectPoint(host.location(), trafficSelector.build());
338 }
339}