blob: d1d1d1aa512958804c678fbab9a9fd91657d74aa [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;
Luca Prete9c2ee072016-02-16 11:00:44 -080040import 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.
Yi Tseng3bbca2a2016-09-01 17:08:34 +080077 * Single Points to Multi Point intents are created for all the configured
Luca Prete9c2ee072016-02-16 11:00:44 -080078 * 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
Yi Tseng647a5162016-09-02 02:22:13 +080089 confHostPresentCPoint.keySet()
90 .stream()
91 .filter(vlanId -> confHostPresentCPoint.get(vlanId) != null)
Luca Prete9c2ee072016-02-16 11:00:44 -080092 .forEach(vlanId -> {
Yi Tseng647a5162016-09-02 02:22:13 +080093 Set<Pair<ConnectPoint, MacAddress>> cPoints =
94 confHostPresentCPoint.get(vlanId);
95 cPoints.forEach(cPoint -> {
96 MacAddress mac = cPoint.getValue();
97 ConnectPoint src = cPoint.getKey();
98 Set<ConnectPoint> dsts = cPoints.stream()
99 .map(Pair::getKey)
100 .filter(cp -> !cp.equals(src))
101 .collect(Collectors.toSet());
102 Key brcKey = buildKey(PREFIX_BROADCAST, src, vlanId);
Yi Tseng28767f02016-09-13 04:27:20 -0700103
104 if (intentService.getIntent(brcKey) == null && dsts.size() > 0) {
105 intents.add(buildBrcIntent(brcKey, src, dsts, vlanId));
Yi Tseng647a5162016-09-02 02:22:13 +0800106 }
Yi Tseng28767f02016-09-13 04:27:20 -0700107
108 if (mac != null && countMacInCPoints(cPoints) > 1 &&
109 dsts.size() > 0) {
Yi Tseng647a5162016-09-02 02:22:13 +0800110 Key uniKey = buildKey(PREFIX_UNICAST, src, vlanId);
111 if (intentService.getIntent(uniKey) == null) {
112 MultiPointToSinglePointIntent uniIntent =
113 buildUniIntent(uniKey,
114 dsts,
115 src,
116 vlanId,
117 mac);
118 intents.add(uniIntent);
Luca Prete9c2ee072016-02-16 11:00:44 -0800119 }
120 }
Yi Tseng647a5162016-09-02 02:22:13 +0800121 });
Luca Prete9c2ee072016-02-16 11:00:44 -0800122 });
123 submitIntents(intents);
124 }
125
126 /**
127 * Requests to install the intents passed as argument to the Intent Service.
128 *
129 * @param intents intents to be submitted
130 */
131 private void submitIntents(Collection<Intent> intents) {
Yi Tseng647a5162016-09-02 02:22:13 +0800132 log.debug("Submitting intents to the Intent Synchronizer");
133 intents.forEach(intent -> {
Luca Prete9c2ee072016-02-16 11:00:44 -0800134 intentSynchronizer.submit(intent);
Yi Tseng647a5162016-09-02 02:22:13 +0800135 });
Luca Prete9c2ee072016-02-16 11:00:44 -0800136 }
137
138 /**
139 * Builds a Single Point to Multi Point intent.
140 *
141 * @param src The source Connect Point
142 * @param dsts The destination Connect Points
143 * @return Single Point to Multi Point intent generated.
144 */
145 private SinglePointToMultiPointIntent buildBrcIntent(Key key,
146 ConnectPoint src,
147 Set<ConnectPoint> dsts,
148 VlanId vlanId) {
149 log.debug("Building p2mp intent from {}", src);
150
151 SinglePointToMultiPointIntent intent;
152
153 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
154
155 TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
156 .matchEthDst(MacAddress.BROADCAST)
157 .matchVlanId(vlanId);
158
159 TrafficSelector selector = builder.build();
160
161 intent = SinglePointToMultiPointIntent.builder()
162 .appId(appId)
163 .key(key)
164 .selector(selector)
165 .treatment(treatment)
166 .ingressPoint(src)
167 .egressPoints(dsts)
168 .priority(PRIORITY_OFFSET)
169 .build();
170 return intent;
171 }
172
173 /**
174 * Builds a Multi Point to Single Point intent.
175 *
176 * @param srcs The source Connect Points
177 * @param dst The destination Connect Point
178 * @return Multi Point to Single Point intent generated.
179 */
180 private MultiPointToSinglePointIntent buildUniIntent(Key key,
181 Set<ConnectPoint> srcs,
182 ConnectPoint dst,
183 VlanId vlanId,
184 MacAddress mac) {
185 log.debug("Building mp2p intent to {}", dst);
186
187 MultiPointToSinglePointIntent intent;
188
189 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
190
191 TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
192 .matchEthDst(mac)
193 .matchVlanId(vlanId);
194
195 TrafficSelector selector = builder.build();
196
197 intent = MultiPointToSinglePointIntent.builder()
198 .appId(appId)
199 .key(key)
200 .selector(selector)
201 .treatment(treatment)
202 .ingressPoints(srcs)
203 .egressPoint(dst)
204 .priority(PRIORITY_OFFSET)
205 .build();
206 return intent;
207 }
208
209 /**
210 * Builds an intent Key for either for a Single Point to Multi Point or
211 * Multi Point to Single Point intent, based on a prefix that defines
212 * the type of intent, the single connection point representing the source
213 * or the destination and the vlan id representing the network.
214 *
215 * @param cPoint the source or destination connect point
216 * @param vlanId the network vlan id
217 * @param prefix prefix string
218 * @return
219 */
220 private Key buildKey(String prefix, ConnectPoint cPoint, VlanId vlanId) {
221 String keyString = new StringBuilder()
222 .append(prefix)
223 .append("-")
224 .append(cPoint.deviceId())
225 .append("-")
226 .append(cPoint.port())
227 .append("-")
228 .append(vlanId)
229 .toString();
230
231 return Key.of(keyString, appId);
232 }
233
234 /**
235 * Counts the number of mac addresses associated to a specific list of
236 * ConnectPoint.
237 *
Yi Tseng647a5162016-09-02 02:22:13 +0800238 * @param cPoints Set of ConnectPoints, eventually bound to the MAC of the
Luca Prete9c2ee072016-02-16 11:00:44 -0800239 * host attached
240 * @return number of mac addresses found.
241 */
Yi Tseng647a5162016-09-02 02:22:13 +0800242 private int countMacInCPoints(Set<Pair<ConnectPoint, MacAddress>> cPoints) {
243 return (int) cPoints.stream().filter(p -> p.getValue() != null).count();
Luca Prete9c2ee072016-02-16 11:00:44 -0800244 }
245
246}