blob: 2cec14a3ffcdf002aebbaef0935877178e9a3309 [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 Prete9c2ee072016-02-16 11:00:44 -080030import org.onosproject.net.intent.Intent;
31import org.onosproject.net.intent.IntentService;
nosignal5fd282e2016-09-16 16:11:40 -070032import org.onosproject.net.intent.IntentState;
Luca Prete9c2ee072016-02-16 11:00:44 -080033import org.onosproject.net.intent.Key;
34import org.onosproject.net.intent.MultiPointToSinglePointIntent;
35import org.onosproject.net.intent.SinglePointToMultiPointIntent;
Luca Prete092e8952016-10-26 16:25:56 +020036import org.onosproject.net.intent.constraint.EncapsulationConstraint;
Luca Prete9c2ee072016-02-16 11:00:44 -080037import org.onosproject.routing.IntentSynchronizationService;
38import org.slf4j.Logger;
39import org.slf4j.LoggerFactory;
40
Luca Prete9c2ee072016-02-16 11:00:44 -080041import java.util.Collection;
Luca Prete9c2ee072016-02-16 11:00:44 -080042import java.util.List;
43import java.util.Set;
Luca Prete9c2ee072016-02-16 11:00:44 -080044
Luca Prete092e8952016-10-26 16:25:56 +020045import static org.onosproject.net.EncapsulationType.*;
46
Luca Prete9c2ee072016-02-16 11:00:44 -080047/**
48 * Synchronizes intents between the in-memory intent store and the
49 * IntentService.
50 */
51public class IntentInstaller {
nosignal5fd282e2016-09-16 16:11:40 -070052 private static final String SUBMIT =
53 "Submitting intents to the Intent Synchronizer";
54 private static final String WITHDRAW =
55 "Withdrawing intents to the Intent Synchronizer";
56 private static final String SP2MP =
57 "Building sp2mp intent from {}";
58 private static final String MP2SP =
59 "Building mp2sp intent to {}";
60
Luca Prete9c2ee072016-02-16 11:00:44 -080061 private static final Logger log = LoggerFactory.getLogger(
62 IntentInstaller.class);
63
64 private static final int PRIORITY_OFFSET = 1000;
65
nosignal5fd282e2016-09-16 16:11:40 -070066 private static final Set<IntentState> WITHDRAWN_INTENT_STATES =
67 ImmutableSet.of(IntentState.WITHDRAWN,
68 IntentState.WITHDRAW_REQ,
69 IntentState.WITHDRAWING);
70
71 static final String PREFIX_BROADCAST = "brc";
72 static final String PREFIX_UNICAST = "uni";
Luca Prete092e8952016-10-26 16:25:56 +020073 static final String SEPARATOR = "-";
Luca Prete9c2ee072016-02-16 11:00:44 -080074
75 private final ApplicationId appId;
76 private final IntentSynchronizationService intentSynchronizer;
77 private final IntentService intentService;
78
79 /**
80 * Class constructor.
81 *
82 * @param appId the Application ID
83 * @param intentService the intent service
84 * @param intentSynchronizer the intent synchronizer service
85 */
86 public IntentInstaller(ApplicationId appId, IntentService intentService,
87 IntentSynchronizationService intentSynchronizer) {
88 this.appId = appId;
89 this.intentService = intentService;
90 this.intentSynchronizer = intentSynchronizer;
91 }
92
93 /**
Luca Prete9c2ee072016-02-16 11:00:44 -080094 * Requests to install the intents passed as argument to the Intent Service.
95 *
96 * @param intents intents to be submitted
97 */
nosignal5fd282e2016-09-16 16:11:40 -070098 protected void submitIntents(Collection<Intent> intents) {
99 log.debug(SUBMIT);
100 intents.forEach(intentSynchronizer::submit);
Luca Prete9c2ee072016-02-16 11:00:44 -0800101 }
102
103 /**
nosignal5fd282e2016-09-16 16:11:40 -0700104 * Requests to withdraw the intents passed as argument to the Intent Service.
Luca Prete9c2ee072016-02-16 11:00:44 -0800105 *
nosignal5fd282e2016-09-16 16:11:40 -0700106 * @param intents intents to be withdraw
Luca Prete9c2ee072016-02-16 11:00:44 -0800107 */
nosignal5fd282e2016-09-16 16:11:40 -0700108 protected void withdrawIntents(Collection<Intent> intents) {
109 log.debug(WITHDRAW);
110 intents.forEach(intentSynchronizer::withdraw);
111 }
112
113 /**
114 * Returns list of intents belongs to a VPLS.
115 *
Luca Prete092e8952016-10-26 16:25:56 +0200116 * @param name the name of the VPLS
117 * @return the list of intents belonging to a VPLS
nosignal5fd282e2016-09-16 16:11:40 -0700118 */
119 protected List<Intent> getIntentsFromVpls(String name) {
120 List<Intent> intents = Lists.newArrayList();
121
122 intentService.getIntents().forEach(intent -> {
123 if (intent.key().toString().startsWith(name)) {
124 intents.add(intent);
125 }
126 });
127
128 return intents;
129 }
130
131 /**
132 * Builds a broadcast intent.
133 *
134 * @param key key to identify the intent
135 * @param src the source connect point
136 * @param dsts the destination connect points
Luca Prete092e8952016-10-26 16:25:56 +0200137 * @param encap the encapsulation type
nosignal5fd282e2016-09-16 16:11:40 -0700138 * @return the generated single-point to multi-point intent
139 */
140 protected SinglePointToMultiPointIntent buildBrcIntent(Key key,
141 FilteredConnectPoint src,
Luca Prete092e8952016-10-26 16:25:56 +0200142 Set<FilteredConnectPoint> dsts,
143 EncapsulationType encap) {
144 log.debug("Building broadcast intent {} for source {}", SP2MP, src);
Luca Prete9c2ee072016-02-16 11:00:44 -0800145
Luca Prete092e8952016-10-26 16:25:56 +0200146 SinglePointToMultiPointIntent.Builder intentBuilder;
Luca Prete9c2ee072016-02-16 11:00:44 -0800147
nosignal5fd282e2016-09-16 16:11:40 -0700148 TrafficSelector selector = DefaultTrafficSelector.builder()
Luca Prete9c2ee072016-02-16 11:00:44 -0800149 .matchEthDst(MacAddress.BROADCAST)
nosignal5fd282e2016-09-16 16:11:40 -0700150 .build();
Luca Prete9c2ee072016-02-16 11:00:44 -0800151
Luca Prete092e8952016-10-26 16:25:56 +0200152 intentBuilder = SinglePointToMultiPointIntent.builder()
Luca Prete9c2ee072016-02-16 11:00:44 -0800153 .appId(appId)
154 .key(key)
155 .selector(selector)
nosignal5fd282e2016-09-16 16:11:40 -0700156 .filteredIngressPoint(src)
157 .filteredEgressPoints(dsts)
Luca Prete092e8952016-10-26 16:25:56 +0200158 .priority(PRIORITY_OFFSET);
159
160 encap(intentBuilder, encap);
161
162 return intentBuilder.build();
Luca Prete9c2ee072016-02-16 11:00:44 -0800163 }
164
165 /**
nosignal5fd282e2016-09-16 16:11:40 -0700166 * Builds a unicast intent.
Luca Prete9c2ee072016-02-16 11:00:44 -0800167 *
nosignal5fd282e2016-09-16 16:11:40 -0700168 * @param key key to identify the intent
169 * @param srcs the source Connect Points
170 * @param dst the destination Connect Point
171 * @param host destination Host
Luca Prete092e8952016-10-26 16:25:56 +0200172 * @param encap the encapsulation type
nosignal5fd282e2016-09-16 16:11:40 -0700173 * @return the generated multi-point to single-point intent
Luca Prete9c2ee072016-02-16 11:00:44 -0800174 */
nosignal5fd282e2016-09-16 16:11:40 -0700175 protected MultiPointToSinglePointIntent buildUniIntent(Key key,
176 Set<FilteredConnectPoint> srcs,
177 FilteredConnectPoint dst,
Luca Prete092e8952016-10-26 16:25:56 +0200178 Host host,
179 EncapsulationType encap) {
180 log.debug("Building unicast intent {} for destination {}", MP2SP, dst);
181
182 MultiPointToSinglePointIntent.Builder intentBuilder;
Luca Prete9c2ee072016-02-16 11:00:44 -0800183
nosignal5fd282e2016-09-16 16:11:40 -0700184 TrafficSelector selector = DefaultTrafficSelector.builder()
185 .matchEthDst(host.mac())
186 .build();
Luca Prete9c2ee072016-02-16 11:00:44 -0800187
Luca Prete092e8952016-10-26 16:25:56 +0200188 intentBuilder = MultiPointToSinglePointIntent.builder()
Luca Prete9c2ee072016-02-16 11:00:44 -0800189 .appId(appId)
190 .key(key)
191 .selector(selector)
nosignal5fd282e2016-09-16 16:11:40 -0700192 .filteredIngressPoints(srcs)
193 .filteredEgressPoint(dst)
Luca Prete092e8952016-10-26 16:25:56 +0200194 .priority(PRIORITY_OFFSET);
nosignal5fd282e2016-09-16 16:11:40 -0700195
Luca Prete092e8952016-10-26 16:25:56 +0200196 encap(intentBuilder, encap);
197
198 return intentBuilder.build();
Luca Prete9c2ee072016-02-16 11:00:44 -0800199 }
200
201 /**
Luca Prete092e8952016-10-26 16:25:56 +0200202 * Builds an intent key either for single-point to multi-point or
203 * multi-point to single-point intents, based on a prefix that defines
204 * the type of intent, the single connect point representing the single
205 * source or destination for that intent, the name of the VPLS the intent
206 * belongs to, and the destination host MAC address the intent reaches.
Luca Prete9c2ee072016-02-16 11:00:44 -0800207 *
Luca Prete092e8952016-10-26 16:25:56 +0200208 * @param prefix the key prefix
209 * @param cPoint the connect point identifying the source/destination
210 * @param vplsName the name of the VPLS
211 * @param hostMac the source/destination MAC address
212 * @return the key to identify the intent
Luca Prete9c2ee072016-02-16 11:00:44 -0800213 */
nosignal5fd282e2016-09-16 16:11:40 -0700214 protected Key buildKey(String prefix,
215 ConnectPoint cPoint,
Luca Prete092e8952016-10-26 16:25:56 +0200216 String vplsName,
nosignal5fd282e2016-09-16 16:11:40 -0700217 MacAddress hostMac) {
Luca Prete092e8952016-10-26 16:25:56 +0200218 String keyString = vplsName +
219 SEPARATOR +
nosignal5fd282e2016-09-16 16:11:40 -0700220 prefix +
Luca Prete092e8952016-10-26 16:25:56 +0200221 SEPARATOR +
nosignal5fd282e2016-09-16 16:11:40 -0700222 cPoint.deviceId() +
Luca Prete092e8952016-10-26 16:25:56 +0200223 SEPARATOR +
nosignal5fd282e2016-09-16 16:11:40 -0700224 cPoint.port() +
Luca Prete092e8952016-10-26 16:25:56 +0200225 SEPARATOR +
nosignal5fd282e2016-09-16 16:11:40 -0700226 hostMac;
Luca Prete9c2ee072016-02-16 11:00:44 -0800227
228 return Key.of(keyString, appId);
229 }
230
231 /**
nosignal5fd282e2016-09-16 16:11:40 -0700232 * Returns true if the specified intent exists; false otherwise.
Luca Prete9c2ee072016-02-16 11:00:44 -0800233 *
Luca Prete092e8952016-10-26 16:25:56 +0200234 * @param intentKey the intent key
235 * @return true if the intent exists; false otherwise
Luca Prete9c2ee072016-02-16 11:00:44 -0800236 */
nosignal5fd282e2016-09-16 16:11:40 -0700237 protected boolean intentExists(Key intentKey) {
238 if (intentService.getIntent(intentKey) == null) {
239 return false;
240 }
Luca Prete9c2ee072016-02-16 11:00:44 -0800241
nosignal5fd282e2016-09-16 16:11:40 -0700242 // Intent does not exist if intent withdrawn
243 IntentState currentIntentState = intentService.getIntentState(intentKey);
Luca Prete092e8952016-10-26 16:25:56 +0200244 return !WITHDRAWN_INTENT_STATES.contains(currentIntentState);
nosignal5fd282e2016-09-16 16:11:40 -0700245
Luca Prete092e8952016-10-26 16:25:56 +0200246 }
247
248 /**
249 * Adds an encapsulation constraint to the builder given, if encap is not
250 * equal to NONE.
251 *
252 * @param builder the intent builder
253 * @param encap the encapsulation type
254 */
255 private static void encap(ConnectivityIntent.Builder builder,
256 EncapsulationType encap) {
257 if (!encap.equals(NONE)) {
258 builder.constraints(ImmutableList.of(
259 new EncapsulationConstraint(encap)));
260 }
nosignal5fd282e2016-09-16 16:11:40 -0700261 }
Luca Prete9c2ee072016-02-16 11:00:44 -0800262}