blob: 79ed71351c48bb89209a1c929220a05d22545757 [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 -070019import org.apache.commons.lang3.tuple.Pair;
Luca Prete9c2ee072016-02-16 11:00:44 -080020import 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;
Luca Prete9c2ee072016-02-16 11:00:44 -080039import java.util.List;
40import java.util.Set;
41import java.util.stream.Collectors;
42
43/**
44 * Synchronizes intents between the in-memory intent store and the
45 * IntentService.
46 */
47public class IntentInstaller {
48 private static final Logger log = LoggerFactory.getLogger(
49 IntentInstaller.class);
50
51 private static final int PRIORITY_OFFSET = 1000;
52
53 private static final String PREFIX_BROADCAST = "brc";
54 private static final String PREFIX_UNICAST = "uni";
55
56 private final ApplicationId appId;
57 private final IntentSynchronizationService intentSynchronizer;
58 private final IntentService intentService;
59
60 /**
61 * Class constructor.
62 *
63 * @param appId the Application ID
64 * @param intentService the intent service
65 * @param intentSynchronizer the intent synchronizer service
66 */
67 public IntentInstaller(ApplicationId appId, IntentService intentService,
68 IntentSynchronizationService intentSynchronizer) {
69 this.appId = appId;
70 this.intentService = intentService;
71 this.intentSynchronizer = intentSynchronizer;
72 }
73
74 /**
75 * Formats the requests for creating and submit intents.
Yi Tseng3bbca2a2016-09-01 17:08:34 +080076 * Single Points to Multi Point intents are created for all the configured
Luca Prete9c2ee072016-02-16 11:00:44 -080077 * Connect Points. Multi Point to Single Point intents are created for
78 * Connect Points configured that have hosts attached.
79 *
80 * @param confHostPresentCPoint A map of Connect Points with the eventual
81 * MAC address of the host attached, by VLAN
82 */
83 protected void installIntents(SetMultimap<VlanId,
84 Pair<ConnectPoint,
85 MacAddress>> confHostPresentCPoint) {
86 List<Intent> intents = new ArrayList<>();
87
Yi Tseng647a5162016-09-02 02:22:13 +080088 confHostPresentCPoint.keySet()
89 .stream()
90 .filter(vlanId -> confHostPresentCPoint.get(vlanId) != null)
Luca Prete9c2ee072016-02-16 11:00:44 -080091 .forEach(vlanId -> {
Yi Tseng647a5162016-09-02 02:22:13 +080092 Set<Pair<ConnectPoint, MacAddress>> cPoints =
93 confHostPresentCPoint.get(vlanId);
94 cPoints.forEach(cPoint -> {
95 MacAddress mac = cPoint.getValue();
96 ConnectPoint src = cPoint.getKey();
97 Set<ConnectPoint> dsts = cPoints.stream()
98 .map(Pair::getKey)
99 .filter(cp -> !cp.equals(src))
100 .collect(Collectors.toSet());
101 Key brcKey = buildKey(PREFIX_BROADCAST, src, vlanId);
Yi Tseng28767f02016-09-13 04:27:20 -0700102
Luca Pretec21c6e62016-09-22 14:52:21 -0700103 if (dsts.isEmpty()) {
104 return;
Yi Tseng647a5162016-09-02 02:22:13 +0800105 }
Yi Tseng28767f02016-09-13 04:27:20 -0700106
Luca Pretec21c6e62016-09-22 14:52:21 -0700107 intents.add(buildBrcIntent(brcKey, src, dsts, vlanId));
108
109 if (mac != null && countMacInCPoints(cPoints) > 1) {
Yi Tseng647a5162016-09-02 02:22:13 +0800110 Key uniKey = buildKey(PREFIX_UNICAST, src, vlanId);
Luca Pretec21c6e62016-09-22 14:52:21 -0700111 MultiPointToSinglePointIntent uniIntent =
112 buildUniIntent(uniKey,
113 dsts,
114 src,
115 vlanId,
116 mac);
117 intents.add(uniIntent);
Luca Prete9c2ee072016-02-16 11:00:44 -0800118 }
Yi Tseng647a5162016-09-02 02:22:13 +0800119 });
Luca Prete9c2ee072016-02-16 11:00:44 -0800120 });
121 submitIntents(intents);
122 }
123
124 /**
125 * Requests to install the intents passed as argument to the Intent Service.
126 *
127 * @param intents intents to be submitted
128 */
129 private void submitIntents(Collection<Intent> intents) {
Yi Tseng647a5162016-09-02 02:22:13 +0800130 log.debug("Submitting intents to the Intent Synchronizer");
131 intents.forEach(intent -> {
Luca Prete9c2ee072016-02-16 11:00:44 -0800132 intentSynchronizer.submit(intent);
Yi Tseng647a5162016-09-02 02:22:13 +0800133 });
Luca Prete9c2ee072016-02-16 11:00:44 -0800134 }
135
136 /**
137 * Builds a Single Point to Multi Point intent.
138 *
139 * @param src The source Connect Point
140 * @param dsts The destination Connect Points
141 * @return Single Point to Multi Point intent generated.
142 */
143 private SinglePointToMultiPointIntent buildBrcIntent(Key key,
144 ConnectPoint src,
145 Set<ConnectPoint> dsts,
146 VlanId vlanId) {
147 log.debug("Building p2mp intent from {}", src);
148
149 SinglePointToMultiPointIntent intent;
150
151 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
152
153 TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
154 .matchEthDst(MacAddress.BROADCAST)
155 .matchVlanId(vlanId);
156
157 TrafficSelector selector = builder.build();
158
159 intent = SinglePointToMultiPointIntent.builder()
160 .appId(appId)
161 .key(key)
162 .selector(selector)
163 .treatment(treatment)
164 .ingressPoint(src)
165 .egressPoints(dsts)
166 .priority(PRIORITY_OFFSET)
167 .build();
168 return intent;
169 }
170
171 /**
172 * Builds a Multi Point to Single Point intent.
173 *
174 * @param srcs The source Connect Points
175 * @param dst The destination Connect Point
176 * @return Multi Point to Single Point intent generated.
177 */
178 private MultiPointToSinglePointIntent buildUniIntent(Key key,
179 Set<ConnectPoint> srcs,
180 ConnectPoint dst,
181 VlanId vlanId,
182 MacAddress mac) {
183 log.debug("Building mp2p intent to {}", dst);
184
185 MultiPointToSinglePointIntent intent;
186
187 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
188
189 TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
190 .matchEthDst(mac)
191 .matchVlanId(vlanId);
192
193 TrafficSelector selector = builder.build();
194
195 intent = MultiPointToSinglePointIntent.builder()
196 .appId(appId)
197 .key(key)
198 .selector(selector)
199 .treatment(treatment)
200 .ingressPoints(srcs)
201 .egressPoint(dst)
202 .priority(PRIORITY_OFFSET)
203 .build();
204 return intent;
205 }
206
207 /**
208 * Builds an intent Key for either for a Single Point to Multi Point or
209 * Multi Point to Single Point intent, based on a prefix that defines
210 * the type of intent, the single connection point representing the source
211 * or the destination and the vlan id representing the network.
212 *
213 * @param cPoint the source or destination connect point
214 * @param vlanId the network vlan id
215 * @param prefix prefix string
216 * @return
217 */
218 private Key buildKey(String prefix, ConnectPoint cPoint, VlanId vlanId) {
219 String keyString = new StringBuilder()
220 .append(prefix)
221 .append("-")
222 .append(cPoint.deviceId())
223 .append("-")
224 .append(cPoint.port())
225 .append("-")
226 .append(vlanId)
227 .toString();
228
229 return Key.of(keyString, appId);
230 }
231
232 /**
233 * Counts the number of mac addresses associated to a specific list of
234 * ConnectPoint.
235 *
Yi Tseng647a5162016-09-02 02:22:13 +0800236 * @param cPoints Set of ConnectPoints, eventually bound to the MAC of the
Luca Prete9c2ee072016-02-16 11:00:44 -0800237 * host attached
238 * @return number of mac addresses found.
239 */
Yi Tseng647a5162016-09-02 02:22:13 +0800240 private int countMacInCPoints(Set<Pair<ConnectPoint, MacAddress>> cPoints) {
241 return (int) cPoints.stream().filter(p -> p.getValue() != null).count();
Luca Prete9c2ee072016-02-16 11:00:44 -0800242 }
243
244}