blob: 94b819adedf8fe927ab1247e663c241506dc28b4 [file] [log] [blame]
Brian O'Connor7cbbbb72016-04-09 02:13:23 -07001/*
2 * Copyright 2016-present Open Networking Laboratory
3 *
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 */
Luca Prete9c2ee072016-02-16 11:00:44 -080016package org.onosproject.vpls;
17
Luca Prete092e8952016-10-26 16:25:56 +020018import com.google.common.collect.ImmutableList;
nosignal5fd282e2016-09-16 16:11:40 -070019import com.google.common.collect.ImmutableSet;
20import com.google.common.collect.Lists;
Luca Prete9c2ee072016-02-16 11:00:44 -080021import org.onlab.packet.MacAddress;
Luca Prete9c2ee072016-02-16 11:00:44 -080022import org.onosproject.core.ApplicationId;
23import org.onosproject.net.ConnectPoint;
Luca Prete092e8952016-10-26 16:25:56 +020024import org.onosproject.net.EncapsulationType;
nosignal5fd282e2016-09-16 16:11:40 -070025import org.onosproject.net.FilteredConnectPoint;
26import org.onosproject.net.Host;
Luca Prete9c2ee072016-02-16 11:00:44 -080027import org.onosproject.net.flow.DefaultTrafficSelector;
Luca Prete9c2ee072016-02-16 11:00:44 -080028import org.onosproject.net.flow.TrafficSelector;
Luca Prete092e8952016-10-26 16:25:56 +020029import org.onosproject.net.intent.ConnectivityIntent;
Luca Prete13465642017-01-04 10:31:48 -080030import org.onosproject.net.intent.Constraint;
Luca Prete9c2ee072016-02-16 11:00:44 -080031import org.onosproject.net.intent.Intent;
32import org.onosproject.net.intent.IntentService;
nosignal5fd282e2016-09-16 16:11:40 -070033import org.onosproject.net.intent.IntentState;
Luca Prete9c2ee072016-02-16 11:00:44 -080034import org.onosproject.net.intent.Key;
35import org.onosproject.net.intent.MultiPointToSinglePointIntent;
36import org.onosproject.net.intent.SinglePointToMultiPointIntent;
Luca Prete092e8952016-10-26 16:25:56 +020037import org.onosproject.net.intent.constraint.EncapsulationConstraint;
Luca Prete13465642017-01-04 10:31:48 -080038import org.onosproject.net.intent.constraint.PartialFailureConstraint;
Jonathan Hart470ed4f2017-01-31 16:52:28 -080039import org.onosproject.intentsync.IntentSynchronizationService;
Luca Prete9c2ee072016-02-16 11:00:44 -080040import org.slf4j.Logger;
41import org.slf4j.LoggerFactory;
42
Luca Prete13465642017-01-04 10:31:48 -080043import java.util.ArrayList;
Luca Prete9c2ee072016-02-16 11:00:44 -080044import java.util.Collection;
Luca Prete9c2ee072016-02-16 11:00:44 -080045import java.util.List;
46import java.util.Set;
Luca Prete9c2ee072016-02-16 11:00:44 -080047
Luca Prete092e8952016-10-26 16:25:56 +020048import static org.onosproject.net.EncapsulationType.*;
49
Luca Prete9c2ee072016-02-16 11:00:44 -080050/**
51 * Synchronizes intents between the in-memory intent store and the
52 * IntentService.
53 */
54public class IntentInstaller {
nosignal5fd282e2016-09-16 16:11:40 -070055 private static final String SUBMIT =
56 "Submitting intents to the Intent Synchronizer";
57 private static final String WITHDRAW =
58 "Withdrawing intents to the Intent Synchronizer";
59 private static final String SP2MP =
60 "Building sp2mp intent from {}";
61 private static final String MP2SP =
62 "Building mp2sp intent to {}";
63
Luca Prete9c2ee072016-02-16 11:00:44 -080064 private static final Logger log = LoggerFactory.getLogger(
65 IntentInstaller.class);
66
67 private static final int PRIORITY_OFFSET = 1000;
68
nosignal5fd282e2016-09-16 16:11:40 -070069 private static final Set<IntentState> WITHDRAWN_INTENT_STATES =
70 ImmutableSet.of(IntentState.WITHDRAWN,
71 IntentState.WITHDRAW_REQ,
72 IntentState.WITHDRAWING);
73
74 static final String PREFIX_BROADCAST = "brc";
75 static final String PREFIX_UNICAST = "uni";
Luca Prete092e8952016-10-26 16:25:56 +020076 static final String SEPARATOR = "-";
Luca Prete9c2ee072016-02-16 11:00:44 -080077
78 private final ApplicationId appId;
79 private final IntentSynchronizationService intentSynchronizer;
80 private final IntentService intentService;
81
Luca Prete13465642017-01-04 10:31:48 -080082 public static final ImmutableList<Constraint> PARTIAL_FAILURE_CONSTRAINT =
83 ImmutableList.of(new PartialFailureConstraint());
84
Luca Prete9c2ee072016-02-16 11:00:44 -080085 /**
86 * Class constructor.
87 *
88 * @param appId the Application ID
89 * @param intentService the intent service
90 * @param intentSynchronizer the intent synchronizer service
91 */
92 public IntentInstaller(ApplicationId appId, IntentService intentService,
93 IntentSynchronizationService intentSynchronizer) {
94 this.appId = appId;
95 this.intentService = intentService;
96 this.intentSynchronizer = intentSynchronizer;
97 }
98
99 /**
Luca Prete9c2ee072016-02-16 11:00:44 -0800100 * Requests to install the intents passed as argument to the Intent Service.
101 *
102 * @param intents intents to be submitted
103 */
nosignal5fd282e2016-09-16 16:11:40 -0700104 protected void submitIntents(Collection<Intent> intents) {
105 log.debug(SUBMIT);
106 intents.forEach(intentSynchronizer::submit);
Luca Prete9c2ee072016-02-16 11:00:44 -0800107 }
108
109 /**
nosignal5fd282e2016-09-16 16:11:40 -0700110 * Requests to withdraw the intents passed as argument to the Intent Service.
Luca Prete9c2ee072016-02-16 11:00:44 -0800111 *
nosignal5fd282e2016-09-16 16:11:40 -0700112 * @param intents intents to be withdraw
Luca Prete9c2ee072016-02-16 11:00:44 -0800113 */
nosignal5fd282e2016-09-16 16:11:40 -0700114 protected void withdrawIntents(Collection<Intent> intents) {
115 log.debug(WITHDRAW);
116 intents.forEach(intentSynchronizer::withdraw);
117 }
118
119 /**
120 * Returns list of intents belongs to a VPLS.
121 *
Luca Prete092e8952016-10-26 16:25:56 +0200122 * @param name the name of the VPLS
123 * @return the list of intents belonging to a VPLS
nosignal5fd282e2016-09-16 16:11:40 -0700124 */
125 protected List<Intent> getIntentsFromVpls(String name) {
126 List<Intent> intents = Lists.newArrayList();
127
128 intentService.getIntents().forEach(intent -> {
129 if (intent.key().toString().startsWith(name)) {
130 intents.add(intent);
131 }
132 });
133
134 return intents;
135 }
136
137 /**
138 * Builds a broadcast intent.
139 *
140 * @param key key to identify the intent
141 * @param src the source connect point
142 * @param dsts the destination connect points
Luca Prete092e8952016-10-26 16:25:56 +0200143 * @param encap the encapsulation type
nosignal5fd282e2016-09-16 16:11:40 -0700144 * @return the generated single-point to multi-point intent
145 */
146 protected SinglePointToMultiPointIntent buildBrcIntent(Key key,
147 FilteredConnectPoint src,
Luca Prete092e8952016-10-26 16:25:56 +0200148 Set<FilteredConnectPoint> dsts,
149 EncapsulationType encap) {
150 log.debug("Building broadcast intent {} for source {}", SP2MP, src);
Luca Prete9c2ee072016-02-16 11:00:44 -0800151
Luca Prete092e8952016-10-26 16:25:56 +0200152 SinglePointToMultiPointIntent.Builder intentBuilder;
Luca Prete9c2ee072016-02-16 11:00:44 -0800153
nosignal5fd282e2016-09-16 16:11:40 -0700154 TrafficSelector selector = DefaultTrafficSelector.builder()
Luca Prete9c2ee072016-02-16 11:00:44 -0800155 .matchEthDst(MacAddress.BROADCAST)
nosignal5fd282e2016-09-16 16:11:40 -0700156 .build();
Luca Prete9c2ee072016-02-16 11:00:44 -0800157
Luca Prete092e8952016-10-26 16:25:56 +0200158 intentBuilder = SinglePointToMultiPointIntent.builder()
Luca Prete9c2ee072016-02-16 11:00:44 -0800159 .appId(appId)
160 .key(key)
161 .selector(selector)
nosignal5fd282e2016-09-16 16:11:40 -0700162 .filteredIngressPoint(src)
163 .filteredEgressPoints(dsts)
Luca Prete13465642017-01-04 10:31:48 -0800164 .constraints(PARTIAL_FAILURE_CONSTRAINT)
Luca Prete092e8952016-10-26 16:25:56 +0200165 .priority(PRIORITY_OFFSET);
166
Luca Prete13465642017-01-04 10:31:48 -0800167 setEncap(intentBuilder, PARTIAL_FAILURE_CONSTRAINT, encap);
Luca Prete092e8952016-10-26 16:25:56 +0200168
169 return intentBuilder.build();
Luca Prete9c2ee072016-02-16 11:00:44 -0800170 }
171
172 /**
nosignal5fd282e2016-09-16 16:11:40 -0700173 * Builds a unicast intent.
Luca Prete9c2ee072016-02-16 11:00:44 -0800174 *
nosignal5fd282e2016-09-16 16:11:40 -0700175 * @param key key to identify the intent
176 * @param srcs the source Connect Points
177 * @param dst the destination Connect Point
178 * @param host destination Host
Luca Prete092e8952016-10-26 16:25:56 +0200179 * @param encap the encapsulation type
nosignal5fd282e2016-09-16 16:11:40 -0700180 * @return the generated multi-point to single-point intent
Luca Prete9c2ee072016-02-16 11:00:44 -0800181 */
nosignal5fd282e2016-09-16 16:11:40 -0700182 protected MultiPointToSinglePointIntent buildUniIntent(Key key,
183 Set<FilteredConnectPoint> srcs,
184 FilteredConnectPoint dst,
Luca Prete092e8952016-10-26 16:25:56 +0200185 Host host,
186 EncapsulationType encap) {
187 log.debug("Building unicast intent {} for destination {}", MP2SP, dst);
188
189 MultiPointToSinglePointIntent.Builder intentBuilder;
Luca Prete9c2ee072016-02-16 11:00:44 -0800190
nosignal5fd282e2016-09-16 16:11:40 -0700191 TrafficSelector selector = DefaultTrafficSelector.builder()
192 .matchEthDst(host.mac())
193 .build();
Luca Prete9c2ee072016-02-16 11:00:44 -0800194
Luca Prete092e8952016-10-26 16:25:56 +0200195 intentBuilder = MultiPointToSinglePointIntent.builder()
Luca Prete9c2ee072016-02-16 11:00:44 -0800196 .appId(appId)
197 .key(key)
198 .selector(selector)
nosignal5fd282e2016-09-16 16:11:40 -0700199 .filteredIngressPoints(srcs)
200 .filteredEgressPoint(dst)
Luca Prete13465642017-01-04 10:31:48 -0800201 .constraints(PARTIAL_FAILURE_CONSTRAINT)
Luca Prete092e8952016-10-26 16:25:56 +0200202 .priority(PRIORITY_OFFSET);
nosignal5fd282e2016-09-16 16:11:40 -0700203
Luca Prete13465642017-01-04 10:31:48 -0800204 setEncap(intentBuilder, PARTIAL_FAILURE_CONSTRAINT, encap);
Luca Prete092e8952016-10-26 16:25:56 +0200205
206 return intentBuilder.build();
Luca Prete9c2ee072016-02-16 11:00:44 -0800207 }
208
209 /**
Luca Prete092e8952016-10-26 16:25:56 +0200210 * Builds an intent key either for single-point to multi-point or
211 * multi-point to single-point intents, based on a prefix that defines
212 * the type of intent, the single connect point representing the single
213 * source or destination for that intent, the name of the VPLS the intent
214 * belongs to, and the destination host MAC address the intent reaches.
Luca Prete9c2ee072016-02-16 11:00:44 -0800215 *
Luca Prete092e8952016-10-26 16:25:56 +0200216 * @param prefix the key prefix
217 * @param cPoint the connect point identifying the source/destination
218 * @param vplsName the name of the VPLS
219 * @param hostMac the source/destination MAC address
220 * @return the key to identify the intent
Luca Prete9c2ee072016-02-16 11:00:44 -0800221 */
nosignal5fd282e2016-09-16 16:11:40 -0700222 protected Key buildKey(String prefix,
223 ConnectPoint cPoint,
Luca Prete092e8952016-10-26 16:25:56 +0200224 String vplsName,
nosignal5fd282e2016-09-16 16:11:40 -0700225 MacAddress hostMac) {
Luca Prete092e8952016-10-26 16:25:56 +0200226 String keyString = vplsName +
227 SEPARATOR +
nosignal5fd282e2016-09-16 16:11:40 -0700228 prefix +
Luca Prete092e8952016-10-26 16:25:56 +0200229 SEPARATOR +
nosignal5fd282e2016-09-16 16:11:40 -0700230 cPoint.deviceId() +
Luca Prete092e8952016-10-26 16:25:56 +0200231 SEPARATOR +
nosignal5fd282e2016-09-16 16:11:40 -0700232 cPoint.port() +
Luca Prete092e8952016-10-26 16:25:56 +0200233 SEPARATOR +
nosignal5fd282e2016-09-16 16:11:40 -0700234 hostMac;
Luca Prete9c2ee072016-02-16 11:00:44 -0800235
236 return Key.of(keyString, appId);
237 }
238
239 /**
nosignal5fd282e2016-09-16 16:11:40 -0700240 * Returns true if the specified intent exists; false otherwise.
Luca Prete9c2ee072016-02-16 11:00:44 -0800241 *
Luca Prete092e8952016-10-26 16:25:56 +0200242 * @param intentKey the intent key
243 * @return true if the intent exists; false otherwise
Luca Prete9c2ee072016-02-16 11:00:44 -0800244 */
nosignal5fd282e2016-09-16 16:11:40 -0700245 protected boolean intentExists(Key intentKey) {
246 if (intentService.getIntent(intentKey) == null) {
247 return false;
248 }
Luca Prete9c2ee072016-02-16 11:00:44 -0800249
nosignal5fd282e2016-09-16 16:11:40 -0700250 // Intent does not exist if intent withdrawn
251 IntentState currentIntentState = intentService.getIntentState(intentKey);
Luca Prete092e8952016-10-26 16:25:56 +0200252 return !WITHDRAWN_INTENT_STATES.contains(currentIntentState);
nosignal5fd282e2016-09-16 16:11:40 -0700253
Luca Prete092e8952016-10-26 16:25:56 +0200254 }
255
256 /**
Luca Prete13465642017-01-04 10:31:48 -0800257 * Sets one or more encapsulation constraints on the intent builder given.
Luca Prete092e8952016-10-26 16:25:56 +0200258 *
259 * @param builder the intent builder
Luca Prete13465642017-01-04 10:31:48 -0800260 * @param constraints the existing intent constraints
261 * @param encap the encapsulation type to be set
Luca Prete092e8952016-10-26 16:25:56 +0200262 */
Luca Prete13465642017-01-04 10:31:48 -0800263 public static void setEncap(ConnectivityIntent.Builder builder,
264 List<Constraint> constraints,
265 EncapsulationType encap) {
266 // Constraints might be an immutable list, so a new modifiable list
267 // is created
268 List<Constraint> newConstraints = new ArrayList<>(constraints);
269
270 // Remove any encapsulation constraint if already in the list
271 constraints.stream()
272 .filter(c -> c instanceof EncapsulationConstraint)
273 .forEach(newConstraints::remove);
274
275 // if the new encapsulation is different from NONE, a new encapsulation
276 // constraint should be added to the list
Luca Prete092e8952016-10-26 16:25:56 +0200277 if (!encap.equals(NONE)) {
Luca Prete13465642017-01-04 10:31:48 -0800278 newConstraints.add(new EncapsulationConstraint(encap));
Luca Prete092e8952016-10-26 16:25:56 +0200279 }
Luca Prete13465642017-01-04 10:31:48 -0800280
281 // Submit new constraint list as immutable list
282 builder.constraints(ImmutableList.copyOf(newConstraints));
nosignal5fd282e2016-09-16 16:11:40 -0700283 }
Luca Prete9c2ee072016-02-16 11:00:44 -0800284}