blob: 080d8ffe2bb654cc116e404a428365b335866601 [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
18import com.google.common.collect.SetMultimap;
19import javafx.util.Pair;
20import org.onlab.packet.MacAddress;
21import org.onlab.packet.VlanId;
22import org.onosproject.core.ApplicationId;
23import org.onosproject.net.ConnectPoint;
24import org.onosproject.net.flow.DefaultTrafficSelector;
25import org.onosproject.net.flow.DefaultTrafficTreatment;
26import org.onosproject.net.flow.TrafficSelector;
27import org.onosproject.net.flow.TrafficTreatment;
28import org.onosproject.net.intent.Intent;
29import org.onosproject.net.intent.IntentService;
30import org.onosproject.net.intent.Key;
31import org.onosproject.net.intent.MultiPointToSinglePointIntent;
32import org.onosproject.net.intent.SinglePointToMultiPointIntent;
33import org.onosproject.routing.IntentSynchronizationService;
34import org.slf4j.Logger;
35import org.slf4j.LoggerFactory;
36
37import java.util.ArrayList;
38import java.util.Collection;
39import java.util.HashSet;
40import java.util.List;
41import java.util.Set;
42import java.util.stream.Collectors;
43
44/**
45 * Synchronizes intents between the in-memory intent store and the
46 * IntentService.
47 */
48public class IntentInstaller {
49 private static final Logger log = LoggerFactory.getLogger(
50 IntentInstaller.class);
51
52 private static final int PRIORITY_OFFSET = 1000;
53
54 private static final String PREFIX_BROADCAST = "brc";
55 private static final String PREFIX_UNICAST = "uni";
56
57 private final ApplicationId appId;
58 private final IntentSynchronizationService intentSynchronizer;
59 private final IntentService intentService;
60
61 /**
62 * Class constructor.
63 *
64 * @param appId the Application ID
65 * @param intentService the intent service
66 * @param intentSynchronizer the intent synchronizer service
67 */
68 public IntentInstaller(ApplicationId appId, IntentService intentService,
69 IntentSynchronizationService intentSynchronizer) {
70 this.appId = appId;
71 this.intentService = intentService;
72 this.intentSynchronizer = intentSynchronizer;
73 }
74
75 /**
76 * Formats the requests for creating and submit intents.
77 * Single Points to Multi Point intents are created for all the conigured
78 * Connect Points. Multi Point to Single Point intents are created for
79 * Connect Points configured that have hosts attached.
80 *
81 * @param confHostPresentCPoint A map of Connect Points with the eventual
82 * MAC address of the host attached, by VLAN
83 */
84 protected void installIntents(SetMultimap<VlanId,
85 Pair<ConnectPoint,
86 MacAddress>> confHostPresentCPoint) {
87 List<Intent> intents = new ArrayList<>();
88
89 confHostPresentCPoint.asMap().keySet()
90 .forEach(vlanId -> {
91 List<Pair<ConnectPoint, MacAddress>> cPoints =
92 confHostPresentCPoint.get(vlanId).stream().collect(Collectors.toList());
93
94 if (cPoints != null && !cPoints.isEmpty()) {
95 for (int i = 0; i < cPoints.size(); i++) {
96 ConnectPoint src = cPoints.get(i).getKey();
97 Set<ConnectPoint> dsts = new HashSet<>();
98 MacAddress mac = cPoints.get(i).getValue();
99 for (int j = 0; j < cPoints.size(); j++) {
100 ConnectPoint dst = cPoints.get(j).getKey();
101 if (!dst.equals(src)) {
102 dsts.add(dst);
103 }
104 }
105 Key brcKey = buildKey(PREFIX_BROADCAST, src, vlanId);
106 if (intentService.getIntent(brcKey) == null) {
107 SinglePointToMultiPointIntent brcIntent =
108 buildBrcIntent(brcKey, src, dsts, vlanId);
109 intents.add(brcIntent);
110 }
111 if (mac != null && countMacInCPoints(cPoints) > 1) {
112 Key uniKey = buildKey(PREFIX_UNICAST, src, vlanId);
113 if (intentService.getIntent(uniKey) == null) {
114 MultiPointToSinglePointIntent uniIntent =
115 buildUniIntent(uniKey,
116 dsts,
117 src,
118 vlanId,
119 mac);
120 intents.add(uniIntent);
121 }
122 }
123 }
124 }
125 });
126 submitIntents(intents);
127 }
128
129 /**
130 * Requests to install the intents passed as argument to the Intent Service.
131 *
132 * @param intents intents to be submitted
133 */
134 private void submitIntents(Collection<Intent> intents) {
135 log.debug("Submitting intents to the IntentSynchronizer");
136
137 for (Intent intent : intents) {
138 intentSynchronizer.submit(intent);
139 }
140 }
141
142 /**
143 * Builds a Single Point to Multi Point intent.
144 *
145 * @param src The source Connect Point
146 * @param dsts The destination Connect Points
147 * @return Single Point to Multi Point intent generated.
148 */
149 private SinglePointToMultiPointIntent buildBrcIntent(Key key,
150 ConnectPoint src,
151 Set<ConnectPoint> dsts,
152 VlanId vlanId) {
153 log.debug("Building p2mp intent from {}", src);
154
155 SinglePointToMultiPointIntent intent;
156
157 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
158
159 TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
160 .matchEthDst(MacAddress.BROADCAST)
161 .matchVlanId(vlanId);
162
163 TrafficSelector selector = builder.build();
164
165 intent = SinglePointToMultiPointIntent.builder()
166 .appId(appId)
167 .key(key)
168 .selector(selector)
169 .treatment(treatment)
170 .ingressPoint(src)
171 .egressPoints(dsts)
172 .priority(PRIORITY_OFFSET)
173 .build();
174 return intent;
175 }
176
177 /**
178 * Builds a Multi Point to Single Point intent.
179 *
180 * @param srcs The source Connect Points
181 * @param dst The destination Connect Point
182 * @return Multi Point to Single Point intent generated.
183 */
184 private MultiPointToSinglePointIntent buildUniIntent(Key key,
185 Set<ConnectPoint> srcs,
186 ConnectPoint dst,
187 VlanId vlanId,
188 MacAddress mac) {
189 log.debug("Building mp2p intent to {}", dst);
190
191 MultiPointToSinglePointIntent intent;
192
193 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
194
195 TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
196 .matchEthDst(mac)
197 .matchVlanId(vlanId);
198
199 TrafficSelector selector = builder.build();
200
201 intent = MultiPointToSinglePointIntent.builder()
202 .appId(appId)
203 .key(key)
204 .selector(selector)
205 .treatment(treatment)
206 .ingressPoints(srcs)
207 .egressPoint(dst)
208 .priority(PRIORITY_OFFSET)
209 .build();
210 return intent;
211 }
212
213 /**
214 * Builds an intent Key for either for a Single Point to Multi Point or
215 * Multi Point to Single Point intent, based on a prefix that defines
216 * the type of intent, the single connection point representing the source
217 * or the destination and the vlan id representing the network.
218 *
219 * @param cPoint the source or destination connect point
220 * @param vlanId the network vlan id
221 * @param prefix prefix string
222 * @return
223 */
224 private Key buildKey(String prefix, ConnectPoint cPoint, VlanId vlanId) {
225 String keyString = new StringBuilder()
226 .append(prefix)
227 .append("-")
228 .append(cPoint.deviceId())
229 .append("-")
230 .append(cPoint.port())
231 .append("-")
232 .append(vlanId)
233 .toString();
234
235 return Key.of(keyString, appId);
236 }
237
238 /**
239 * Counts the number of mac addresses associated to a specific list of
240 * ConnectPoint.
241 *
242 * @param cPoints List of ConnectPoints, eventually binded to the MAC of the
243 * host attached
244 * @return number of mac addresses found.
245 */
246 private int countMacInCPoints(List<Pair<ConnectPoint, MacAddress>> cPoints) {
247 int macFound = 0;
248 for (Pair<ConnectPoint, MacAddress> p : cPoints) {
249 if (p.getValue() != null) {
250 macFound++;
251 }
252 }
253 return macFound;
254 }
255
256}