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