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