blob: 013461e9cb0a2eb96dbde80318416a72f1a01786 [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);
103 if (intentService.getIntent(brcKey) == null) {
104 SinglePointToMultiPointIntent brcIntent =
105 buildBrcIntent(brcKey, src, dsts, vlanId);
106 intents.add(brcIntent);
107 }
108 if (mac != null && countMacInCPoints(cPoints) > 1) {
109 Key uniKey = buildKey(PREFIX_UNICAST, src, vlanId);
110 if (intentService.getIntent(uniKey) == null) {
111 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 }
119 }
Yi Tseng647a5162016-09-02 02:22:13 +0800120 });
Luca Prete9c2ee072016-02-16 11:00:44 -0800121 });
122 submitIntents(intents);
123 }
124
125 /**
126 * Requests to install the intents passed as argument to the Intent Service.
127 *
128 * @param intents intents to be submitted
129 */
130 private void submitIntents(Collection<Intent> intents) {
Yi Tseng647a5162016-09-02 02:22:13 +0800131 log.debug("Submitting intents to the Intent Synchronizer");
132 intents.forEach(intent -> {
Luca Prete9c2ee072016-02-16 11:00:44 -0800133 intentSynchronizer.submit(intent);
Yi Tseng647a5162016-09-02 02:22:13 +0800134 });
Luca Prete9c2ee072016-02-16 11:00:44 -0800135 }
136
137 /**
138 * Builds a Single Point to Multi Point intent.
139 *
140 * @param src The source Connect Point
141 * @param dsts The destination Connect Points
142 * @return Single Point to Multi Point intent generated.
143 */
144 private SinglePointToMultiPointIntent buildBrcIntent(Key key,
145 ConnectPoint src,
146 Set<ConnectPoint> dsts,
147 VlanId vlanId) {
148 log.debug("Building p2mp intent from {}", src);
149
150 SinglePointToMultiPointIntent intent;
151
152 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
153
154 TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
155 .matchEthDst(MacAddress.BROADCAST)
156 .matchVlanId(vlanId);
157
158 TrafficSelector selector = builder.build();
159
160 intent = SinglePointToMultiPointIntent.builder()
161 .appId(appId)
162 .key(key)
163 .selector(selector)
164 .treatment(treatment)
165 .ingressPoint(src)
166 .egressPoints(dsts)
167 .priority(PRIORITY_OFFSET)
168 .build();
169 return intent;
170 }
171
172 /**
173 * Builds a Multi Point to Single Point intent.
174 *
175 * @param srcs The source Connect Points
176 * @param dst The destination Connect Point
177 * @return Multi Point to Single Point intent generated.
178 */
179 private MultiPointToSinglePointIntent buildUniIntent(Key key,
180 Set<ConnectPoint> srcs,
181 ConnectPoint dst,
182 VlanId vlanId,
183 MacAddress mac) {
184 log.debug("Building mp2p intent to {}", dst);
185
186 MultiPointToSinglePointIntent intent;
187
188 TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
189
190 TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
191 .matchEthDst(mac)
192 .matchVlanId(vlanId);
193
194 TrafficSelector selector = builder.build();
195
196 intent = MultiPointToSinglePointIntent.builder()
197 .appId(appId)
198 .key(key)
199 .selector(selector)
200 .treatment(treatment)
201 .ingressPoints(srcs)
202 .egressPoint(dst)
203 .priority(PRIORITY_OFFSET)
204 .build();
205 return intent;
206 }
207
208 /**
209 * Builds an intent Key for either for a Single Point to Multi Point or
210 * Multi Point to Single Point intent, based on a prefix that defines
211 * the type of intent, the single connection point representing the source
212 * or the destination and the vlan id representing the network.
213 *
214 * @param cPoint the source or destination connect point
215 * @param vlanId the network vlan id
216 * @param prefix prefix string
217 * @return
218 */
219 private Key buildKey(String prefix, ConnectPoint cPoint, VlanId vlanId) {
220 String keyString = new StringBuilder()
221 .append(prefix)
222 .append("-")
223 .append(cPoint.deviceId())
224 .append("-")
225 .append(cPoint.port())
226 .append("-")
227 .append(vlanId)
228 .toString();
229
230 return Key.of(keyString, appId);
231 }
232
233 /**
234 * Counts the number of mac addresses associated to a specific list of
235 * ConnectPoint.
236 *
Yi Tseng647a5162016-09-02 02:22:13 +0800237 * @param cPoints Set of ConnectPoints, eventually bound to the MAC of the
Luca Prete9c2ee072016-02-16 11:00:44 -0800238 * host attached
239 * @return number of mac addresses found.
240 */
Yi Tseng647a5162016-09-02 02:22:13 +0800241 private int countMacInCPoints(Set<Pair<ConnectPoint, MacAddress>> cPoints) {
242 return (int) cPoints.stream().filter(p -> p.getValue() != null).count();
Luca Prete9c2ee072016-02-16 11:00:44 -0800243 }
244
245}