blob: 7e8cb4c1312176178fa13b8fe88ff41edbc7bebf [file] [log] [blame]
sanghob35a6192015-04-01 13:05:26 -07001/*
2 * Copyright 2015 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 */
16package org.onosproject.segmentrouting;
17
sangho20eff1d2015-04-13 15:15:58 -070018import com.google.common.collect.Maps;
19import com.google.common.collect.Sets;
sangho666cd6d2015-04-14 16:27:13 -070020import org.onlab.packet.Ip4Address;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070021import org.onlab.packet.Ip4Prefix;
sanghob35a6192015-04-01 13:05:26 -070022import org.onlab.packet.IpPrefix;
23import org.onosproject.net.Device;
24import org.onosproject.net.DeviceId;
sangho20eff1d2015-04-13 15:15:58 -070025import org.onosproject.net.Link;
sanghob35a6192015-04-01 13:05:26 -070026import org.onosproject.net.MastershipRole;
sanghob35a6192015-04-01 13:05:26 -070027import org.slf4j.Logger;
28import org.slf4j.LoggerFactory;
29
30import java.util.ArrayList;
31import java.util.HashMap;
32import java.util.HashSet;
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -070033import java.util.List;
sanghob35a6192015-04-01 13:05:26 -070034import java.util.Set;
35
36import static com.google.common.base.Preconditions.checkNotNull;
37
38public class DefaultRoutingHandler {
39
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070040 private static Logger log = LoggerFactory
41 .getLogger(DefaultRoutingHandler.class);
sanghob35a6192015-04-01 13:05:26 -070042
43 private SegmentRoutingManager srManager;
44 private RoutingRulePopulator rulePopulator;
sangho20eff1d2015-04-13 15:15:58 -070045 private HashMap<DeviceId, ECMPShortestPathGraph> currentEcmpSpgMap;
sangho45b009c2015-05-07 13:30:57 -070046 private HashMap<DeviceId, ECMPShortestPathGraph> updatedEcmpSpgMap;
sangho666cd6d2015-04-14 16:27:13 -070047 private DeviceConfiguration config;
sanghob35a6192015-04-01 13:05:26 -070048 private Status populationStatus;
49
50 /**
51 * Represents the default routing population status.
52 */
53 public enum Status {
54 // population process is not started yet.
55 IDLE,
56
57 // population process started.
58 STARTED,
59
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070060 // population process was aborted due to errors, mostly for groups not
61 // found.
sanghob35a6192015-04-01 13:05:26 -070062 ABORTED,
63
64 // population process was finished successfully.
65 SUCCEEDED
66 }
67
68 /**
69 * Creates a DefaultRoutingHandler object.
70 *
71 * @param srManager SegmentRoutingManager object
72 */
73 public DefaultRoutingHandler(SegmentRoutingManager srManager) {
74 this.srManager = srManager;
75 this.rulePopulator = checkNotNull(srManager.routingRulePopulator);
sangho666cd6d2015-04-14 16:27:13 -070076 this.config = checkNotNull(srManager.deviceConfiguration);
sanghob35a6192015-04-01 13:05:26 -070077 this.populationStatus = Status.IDLE;
sangho20eff1d2015-04-13 15:15:58 -070078 this.currentEcmpSpgMap = Maps.newHashMap();
sanghob35a6192015-04-01 13:05:26 -070079 }
80
81 /**
82 * Populates all routing rules to all connected routers, including default
83 * routing rules, adjacency rules, and policy rules if any.
84 *
85 * @return true if it succeeds in populating all rules, otherwise false
86 */
87 public boolean populateAllRoutingRules() {
88
89 populationStatus = Status.STARTED;
sangho20eff1d2015-04-13 15:15:58 -070090 rulePopulator.resetCounter();
sanghob35a6192015-04-01 13:05:26 -070091 log.info("Starts to populate routing rules");
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070092 log.debug("populateAllRoutingRules: populationStatus is STARTED");
sanghob35a6192015-04-01 13:05:26 -070093
94 for (Device sw : srManager.deviceService.getDevices()) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -070095 if (srManager.mastershipService.getLocalRole(sw.id()) != MastershipRole.MASTER) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -070096 log.debug("populateAllRoutingRules: skipping device {}...we are not master",
97 sw.id());
sanghob35a6192015-04-01 13:05:26 -070098 continue;
99 }
100
sangho20eff1d2015-04-13 15:15:58 -0700101 ECMPShortestPathGraph ecmpSpg = new ECMPShortestPathGraph(sw.id(), srManager);
102 if (!populateEcmpRoutingRules(sw.id(), ecmpSpg)) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700103 log.debug("populateAllRoutingRules: populationStatus is ABORTED");
sanghob35a6192015-04-01 13:05:26 -0700104 populationStatus = Status.ABORTED;
105 log.debug("Abort routing rule population");
106 return false;
107 }
sangho20eff1d2015-04-13 15:15:58 -0700108 currentEcmpSpgMap.put(sw.id(), ecmpSpg);
sanghob35a6192015-04-01 13:05:26 -0700109
110 // TODO: Set adjacency routing rule for all switches
111 }
112
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700113 log.debug("populateAllRoutingRules: populationStatus is SUCCEEDED");
sanghob35a6192015-04-01 13:05:26 -0700114 populationStatus = Status.SUCCEEDED;
sangho20eff1d2015-04-13 15:15:58 -0700115 log.info("Completes routing rule population. Total # of rules pushed : {}",
116 rulePopulator.getCounter());
sanghob35a6192015-04-01 13:05:26 -0700117 return true;
118 }
119
sangho20eff1d2015-04-13 15:15:58 -0700120 /**
121 * Populates the routing rules according to the route changes due to the link
122 * failure or link add. It computes the routes changed due to the link changes and
123 * repopulates the rules only for the routes.
124 *
125 * @param linkFail link failed, null for link added
126 * @return true if it succeeds to populate all rules, false otherwise
127 */
128 public boolean populateRoutingRulesForLinkStatusChange(Link linkFail) {
129
130 synchronized (populationStatus) {
131
132 if (populationStatus == Status.STARTED) {
sangho52abe3a2015-05-05 14:13:34 -0700133 log.warn("Previous rule population is not finished.");
sangho20eff1d2015-04-13 15:15:58 -0700134 return true;
135 }
136
sangho45b009c2015-05-07 13:30:57 -0700137 // Take the snapshots of the links
138 updatedEcmpSpgMap = new HashMap<>();
139 for (Device sw : srManager.deviceService.getDevices()) {
140 if (srManager.mastershipService.
141 getLocalRole(sw.id()) != MastershipRole.MASTER) {
142 continue;
143 }
144 ECMPShortestPathGraph ecmpSpgUpdated =
145 new ECMPShortestPathGraph(sw.id(), srManager);
146 updatedEcmpSpgMap.put(sw.id(), ecmpSpgUpdated);
147 }
148
sangho52abe3a2015-05-05 14:13:34 -0700149 log.info("Starts rule population from link change");
150
sangho20eff1d2015-04-13 15:15:58 -0700151 Set<ArrayList<DeviceId>> routeChanges;
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700152 log.trace("populateRoutingRulesForLinkStatusChange: "
153 + "populationStatus is STARTED");
sangho20eff1d2015-04-13 15:15:58 -0700154 populationStatus = Status.STARTED;
155 if (linkFail == null) {
156 // Compare all routes of existing ECMP SPG with the new ones
157 routeChanges = computeRouteChange();
158 } else {
159 // Compare existing ECMP SPG only with the link removed
160 routeChanges = computeDamagedRoutes(linkFail);
161 }
162
163 if (routeChanges.isEmpty()) {
sangho52abe3a2015-05-05 14:13:34 -0700164 log.info("No route changes for the link status change");
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700165 log.debug("populateRoutingRulesForLinkStatusChange: populationStatus is SUCCEEDED");
sangho20eff1d2015-04-13 15:15:58 -0700166 populationStatus = Status.SUCCEEDED;
167 return true;
168 }
169
170 if (repopulateRoutingRulesForRoutes(routeChanges)) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700171 log.debug("populateRoutingRulesForLinkStatusChange: populationStatus is SUCCEEDED");
sangho20eff1d2015-04-13 15:15:58 -0700172 populationStatus = Status.SUCCEEDED;
173 log.info("Complete to repopulate the rules. # of rules populated : {}",
174 rulePopulator.getCounter());
175 return true;
176 } else {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700177 log.debug("populateRoutingRulesForLinkStatusChange: populationStatus is ABORTED");
sangho20eff1d2015-04-13 15:15:58 -0700178 populationStatus = Status.ABORTED;
179 log.warn("Failed to repopulate the rules.");
180 return false;
181 }
182 }
183 }
184
185 private boolean repopulateRoutingRulesForRoutes(Set<ArrayList<DeviceId>> routes) {
186 rulePopulator.resetCounter();
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700187 HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> routesBydevice =
188 new HashMap<>();
sangho20eff1d2015-04-13 15:15:58 -0700189 for (ArrayList<DeviceId> link: routes) {
sangho834e4b02015-05-01 09:38:25 -0700190 // When only the source device is defined, reinstall routes to all other devices
sangho20eff1d2015-04-13 15:15:58 -0700191 if (link.size() == 1) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700192 log.trace("repopulateRoutingRulesForRoutes: running ECMP graph for device {}", link.get(0));
sangho20eff1d2015-04-13 15:15:58 -0700193 ECMPShortestPathGraph ecmpSpg = new ECMPShortestPathGraph(link.get(0), srManager);
194 if (populateEcmpRoutingRules(link.get(0), ecmpSpg)) {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700195 log.debug("Populating flow rules from {} to all is successful",
196 link.get(0));
sangho20eff1d2015-04-13 15:15:58 -0700197 currentEcmpSpgMap.put(link.get(0), ecmpSpg);
sangho52abe3a2015-05-05 14:13:34 -0700198 } else {
sangho45b009c2015-05-07 13:30:57 -0700199 log.warn("Failed to populate the flow rules from {} to all", link.get(0));
sangho52abe3a2015-05-05 14:13:34 -0700200 return false;
sangho20eff1d2015-04-13 15:15:58 -0700201 }
sangho45b009c2015-05-07 13:30:57 -0700202 } else {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700203 ArrayList<ArrayList<DeviceId>> deviceRoutes =
204 routesBydevice.get(link.get(1));
205 if (deviceRoutes == null) {
206 deviceRoutes = new ArrayList<>();
207 routesBydevice.put(link.get(1), deviceRoutes);
208 }
209 deviceRoutes.add(link);
210 }
211 }
212
213 for (DeviceId impactedDevice : routesBydevice.keySet()) {
214 ArrayList<ArrayList<DeviceId>> deviceRoutes =
215 routesBydevice.get(impactedDevice);
216 for (ArrayList<DeviceId> link: deviceRoutes) {
217 log.debug("repopulate RoutingRules For Routes {} -> {}",
218 link.get(0), link.get(1));
sangho45b009c2015-05-07 13:30:57 -0700219 DeviceId src = link.get(0);
220 DeviceId dst = link.get(1);
sangho45b009c2015-05-07 13:30:57 -0700221 ECMPShortestPathGraph ecmpSpg = updatedEcmpSpgMap.get(dst);
222 HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia =
223 ecmpSpg.getAllLearnedSwitchesAndVia();
224 for (Integer itrIdx : switchVia.keySet()) {
225 HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> swViaMap =
226 switchVia.get(itrIdx);
227 for (DeviceId targetSw : swViaMap.keySet()) {
228 if (!targetSw.equals(src)) {
229 continue;
230 }
231 Set<DeviceId> nextHops = new HashSet<>();
232 for (ArrayList<DeviceId> via : swViaMap.get(targetSw)) {
233 if (via.isEmpty()) {
234 nextHops.add(dst);
235 } else {
236 nextHops.add(via.get(0));
237 }
238 }
239 if (!populateEcmpRoutingRulePartial(targetSw, dst, nextHops)) {
240 return false;
sangho20eff1d2015-04-13 15:15:58 -0700241 }
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700242 log.debug("Populating flow rules from {} to {} is successful",
243 targetSw, dst);
sangho20eff1d2015-04-13 15:15:58 -0700244 }
sangho20eff1d2015-04-13 15:15:58 -0700245 }
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700246 //currentEcmpSpgMap.put(dst, ecmpSpg);
sangho20eff1d2015-04-13 15:15:58 -0700247 }
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700248 //Only if all the flows for all impacted routes to a
249 //specific target are pushed successfully, update the
250 //ECMP graph for that target. (Or else the next event
251 //would not see any changes in the ECMP graphs)
252 currentEcmpSpgMap.put(impactedDevice,
253 updatedEcmpSpgMap.get(impactedDevice));
sangho20eff1d2015-04-13 15:15:58 -0700254 }
255 return true;
256 }
257
258 private Set<ArrayList<DeviceId>> computeDamagedRoutes(Link linkFail) {
259
260 Set<ArrayList<DeviceId>> routes = new HashSet<>();
261
262 for (Device sw : srManager.deviceService.getDevices()) {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700263 log.debug("Computing the impacted routes for device {} due to link fail",
264 sw.id());
sangho20eff1d2015-04-13 15:15:58 -0700265 if (srManager.mastershipService.
266 getLocalRole(sw.id()) != MastershipRole.MASTER) {
267 continue;
268 }
269 ECMPShortestPathGraph ecmpSpg = currentEcmpSpgMap.get(sw.id());
270 if (ecmpSpg == null) {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700271 log.error("No existing ECMP graph for switch {}", sw.id());
sangho20eff1d2015-04-13 15:15:58 -0700272 continue;
273 }
274 HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia =
275 ecmpSpg.getAllLearnedSwitchesAndVia();
276 for (Integer itrIdx : switchVia.keySet()) {
277 HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> swViaMap =
278 switchVia.get(itrIdx);
279 for (DeviceId targetSw : swViaMap.keySet()) {
280 DeviceId destSw = sw.id();
281 Set<ArrayList<DeviceId>> subLinks =
282 computeLinks(targetSw, destSw, swViaMap);
283 for (ArrayList<DeviceId> alink: subLinks) {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700284 if ((alink.get(0).equals(linkFail.src().deviceId()) &&
285 alink.get(1).equals(linkFail.dst().deviceId()))
286 ||
287 (alink.get(0).equals(linkFail.dst().deviceId()) &&
288 alink.get(1).equals(linkFail.src().deviceId()))) {
289 log.debug("Impacted route:{}->{}", targetSw, destSw);
sangho20eff1d2015-04-13 15:15:58 -0700290 ArrayList<DeviceId> aRoute = new ArrayList<>();
291 aRoute.add(targetSw);
292 aRoute.add(destSw);
293 routes.add(aRoute);
294 break;
295 }
296 }
297 }
298 }
sangho45b009c2015-05-07 13:30:57 -0700299
sangho20eff1d2015-04-13 15:15:58 -0700300 }
301
302 return routes;
303 }
304
305 private Set<ArrayList<DeviceId>> computeRouteChange() {
306
307 Set<ArrayList<DeviceId>> routes = new HashSet<>();
308
309 for (Device sw : srManager.deviceService.getDevices()) {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700310 log.debug("Computing the impacted routes for device {}",
311 sw.id());
sangho20eff1d2015-04-13 15:15:58 -0700312 if (srManager.mastershipService.
313 getLocalRole(sw.id()) != MastershipRole.MASTER) {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700314 log.debug("No mastership for {} and skip route optimization",
315 sw.id());
sangho20eff1d2015-04-13 15:15:58 -0700316 continue;
317 }
sangho45b009c2015-05-07 13:30:57 -0700318
319 log.trace("link of {} - ", sw.id());
320 for (Link link: srManager.linkService.getDeviceLinks(sw.id())) {
321 log.trace("{} -> {} ", link.src().deviceId(), link.dst().deviceId());
322 }
323
324 log.debug("Checking route change for switch {}", sw.id());
sangho20eff1d2015-04-13 15:15:58 -0700325 ECMPShortestPathGraph ecmpSpg = currentEcmpSpgMap.get(sw.id());
326 if (ecmpSpg == null) {
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700327 log.debug("No existing ECMP graph for device {}", sw.id());
sangho20eff1d2015-04-13 15:15:58 -0700328 ArrayList<DeviceId> route = new ArrayList<>();
329 route.add(sw.id());
330 routes.add(route);
331 continue;
332 }
sangho45b009c2015-05-07 13:30:57 -0700333 ECMPShortestPathGraph newEcmpSpg = updatedEcmpSpgMap.get(sw.id());
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700334 //currentEcmpSpgMap.put(sw.id(), newEcmpSpg);
sangho20eff1d2015-04-13 15:15:58 -0700335 HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia =
336 ecmpSpg.getAllLearnedSwitchesAndVia();
337 HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchViaUpdated =
338 newEcmpSpg.getAllLearnedSwitchesAndVia();
339
sangho45b009c2015-05-07 13:30:57 -0700340 for (Integer itrIdx : switchViaUpdated.keySet()) {
341 HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> swViaMapUpdated =
342 switchViaUpdated.get(itrIdx);
343 for (DeviceId srcSw : swViaMapUpdated.keySet()) {
344 ArrayList<ArrayList<DeviceId>> viaUpdated = swViaMapUpdated.get(srcSw);
345 ArrayList<ArrayList<DeviceId>> via = getVia(switchVia, srcSw);
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700346 if ((via == null) || !viaUpdated.equals(via)) {
347 log.debug("Impacted route:{}->{}", srcSw, sw.id());
sangho20eff1d2015-04-13 15:15:58 -0700348 ArrayList<DeviceId> route = new ArrayList<>();
349 route.add(srcSw);
350 route.add(sw.id());
351 routes.add(route);
352 }
353 }
354 }
sangho45b009c2015-05-07 13:30:57 -0700355 }
sangho20eff1d2015-04-13 15:15:58 -0700356
sangho45b009c2015-05-07 13:30:57 -0700357 for (ArrayList<DeviceId> link: routes) {
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700358 log.trace("Route changes - ");
sangho45b009c2015-05-07 13:30:57 -0700359 if (link.size() == 1) {
360 log.trace(" : {} - all", link.get(0));
361 } else {
362 log.trace(" : {} - {}", link.get(0), link.get(1));
363 }
sangho20eff1d2015-04-13 15:15:58 -0700364 }
365
366 return routes;
367 }
368
369 private ArrayList<ArrayList<DeviceId>> getVia(HashMap<Integer, HashMap<DeviceId,
370 ArrayList<ArrayList<DeviceId>>>> switchVia, DeviceId srcSw) {
371 for (Integer itrIdx : switchVia.keySet()) {
372 HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> swViaMap =
373 switchVia.get(itrIdx);
374 if (swViaMap.get(srcSw) == null) {
375 continue;
376 } else {
377 return swViaMap.get(srcSw);
378 }
379 }
380
Srikanth Vavilapalli5428b6c2015-05-14 20:22:47 -0700381 return null;
sangho20eff1d2015-04-13 15:15:58 -0700382 }
383
384 private Set<ArrayList<DeviceId>> computeLinks(DeviceId src,
385 DeviceId dst,
386 HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> viaMap) {
387 Set<ArrayList<DeviceId>> subLinks = Sets.newHashSet();
388 for (ArrayList<DeviceId> via : viaMap.get(src)) {
389 DeviceId linkSrc = src;
390 DeviceId linkDst = dst;
391 for (DeviceId viaDevice: via) {
392 ArrayList<DeviceId> link = new ArrayList<>();
393 linkDst = viaDevice;
394 link.add(linkSrc);
395 link.add(linkDst);
396 subLinks.add(link);
397 linkSrc = viaDevice;
398 }
399 ArrayList<DeviceId> link = new ArrayList<>();
400 link.add(linkSrc);
401 link.add(dst);
402 subLinks.add(link);
403 }
404
405 return subLinks;
406 }
407
408 private boolean populateEcmpRoutingRules(DeviceId destSw,
sanghob35a6192015-04-01 13:05:26 -0700409 ECMPShortestPathGraph ecmpSPG) {
410
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700411 HashMap<Integer, HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>>> switchVia = ecmpSPG
412 .getAllLearnedSwitchesAndVia();
sanghob35a6192015-04-01 13:05:26 -0700413 for (Integer itrIdx : switchVia.keySet()) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700414 HashMap<DeviceId, ArrayList<ArrayList<DeviceId>>> swViaMap = switchVia
415 .get(itrIdx);
sanghob35a6192015-04-01 13:05:26 -0700416 for (DeviceId targetSw : swViaMap.keySet()) {
sanghob35a6192015-04-01 13:05:26 -0700417 Set<DeviceId> nextHops = new HashSet<>();
418
419 for (ArrayList<DeviceId> via : swViaMap.get(targetSw)) {
420 if (via.isEmpty()) {
421 nextHops.add(destSw);
422 } else {
423 nextHops.add(via.get(0));
424 }
425 }
426 if (!populateEcmpRoutingRulePartial(targetSw, destSw, nextHops)) {
427 return false;
428 }
429 }
430 }
431
432 return true;
433 }
434
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700435 private boolean populateEcmpRoutingRulePartial(DeviceId targetSw,
436 DeviceId destSw,
437 Set<DeviceId> nextHops) {
sanghob35a6192015-04-01 13:05:26 -0700438 boolean result;
439
440 if (nextHops.isEmpty()) {
441 nextHops.add(destSw);
442 }
443
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700444 // If both target switch and dest switch are edge routers, then set IP
sangho52abe3a2015-05-05 14:13:34 -0700445 // rule for both subnet and router IP.
sangho666cd6d2015-04-14 16:27:13 -0700446 if (config.isEdgeDevice(targetSw) && config.isEdgeDevice(destSw)) {
447 List<Ip4Prefix> subnets = config.getSubnets(destSw);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700448 log.debug("populateEcmpRoutingRulePartial in device {} towards {} for subnets {}",
449 targetSw, destSw, subnets);
Srikanth Vavilapalli4db76e32015-04-07 15:12:32 -0700450 result = rulePopulator.populateIpRuleForSubnet(targetSw,
451 subnets,
452 destSw,
453 nextHops);
sanghob35a6192015-04-01 13:05:26 -0700454 if (!result) {
455 return false;
456 }
457
sangho666cd6d2015-04-14 16:27:13 -0700458 Ip4Address routerIp = config.getRouterIp(destSw);
459 IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700460 log.debug("populateEcmpRoutingRulePartial in device {} towards {} for router IP {}",
461 targetSw, destSw, routerIpPrefix);
sangho666cd6d2015-04-14 16:27:13 -0700462 result = rulePopulator.populateIpRuleForRouter(targetSw, routerIpPrefix, destSw, nextHops);
sanghob35a6192015-04-01 13:05:26 -0700463 if (!result) {
464 return false;
465 }
466
sangho52abe3a2015-05-05 14:13:34 -0700467 // If the target switch is an edge router, then set IP rules for the router IP.
sangho666cd6d2015-04-14 16:27:13 -0700468 } else if (config.isEdgeDevice(targetSw)) {
469 Ip4Address routerIp = config.getRouterIp(destSw);
470 IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH);
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700471 log.debug("populateEcmpRoutingRulePartial in device {} towards {} for router IP {}",
472 targetSw, destSw, routerIpPrefix);
sangho666cd6d2015-04-14 16:27:13 -0700473 result = rulePopulator.populateIpRuleForRouter(targetSw, routerIpPrefix, destSw, nextHops);
sanghob35a6192015-04-01 13:05:26 -0700474 if (!result) {
475 return false;
476 }
sangho52abe3a2015-05-05 14:13:34 -0700477 }
sanghob35a6192015-04-01 13:05:26 -0700478
sangho52abe3a2015-05-05 14:13:34 -0700479 // Populates MPLS rules to all routers
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700480 log.debug("populateEcmpRoutingRulePartial in device{} towards {} for all MPLS rules",
481 targetSw, destSw);
sangho52abe3a2015-05-05 14:13:34 -0700482 result = rulePopulator.populateMplsRule(targetSw, destSw, nextHops);
483 if (!result) {
484 return false;
sanghob35a6192015-04-01 13:05:26 -0700485 }
486
487 return true;
488 }
489
490 /**
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700491 * Populates table miss entries for all tables, and pipeline rules for VLAN
492 * and TACM tables.
sanghob35a6192015-04-01 13:05:26 -0700493 *
494 * @param deviceId Switch ID to set the rules
495 */
496 public void populateTtpRules(DeviceId deviceId) {
sanghob35a6192015-04-01 13:05:26 -0700497 rulePopulator.populateTableVlan(deviceId);
498 rulePopulator.populateTableTMac(deviceId);
499 }
500
501 /**
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700502 * Start the flow rule population process if it was never started. The
503 * process finishes successfully when all flow rules are set and stops with
504 * ABORTED status when any groups required for flows is not set yet.
sanghob35a6192015-04-01 13:05:26 -0700505 */
506 public void startPopulationProcess() {
507 synchronized (populationStatus) {
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700508 if (populationStatus == Status.IDLE
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700509 || populationStatus == Status.SUCCEEDED
510 || populationStatus == Status.ABORTED) {
sanghob35a6192015-04-01 13:05:26 -0700511 populationStatus = Status.STARTED;
512 populateAllRoutingRules();
Srikanth Vavilapalli23181912015-05-04 09:48:09 -0700513 } else {
514 log.warn("Not initiating startPopulationProcess as populationStatus is {}",
515 populationStatus);
sanghob35a6192015-04-01 13:05:26 -0700516 }
517 }
518 }
519
520 /**
521 * Resume the flow rule population process if it was aborted for any reason.
522 * Mostly the process is aborted when the groups required are not set yet.
523 */
524 public void resumePopulationProcess() {
525 synchronized (populationStatus) {
526 if (populationStatus == Status.ABORTED) {
527 populationStatus = Status.STARTED;
Srikanth Vavilapallif5b234a2015-04-21 13:04:13 -0700528 // TODO: we need to restart from the point aborted instead of
529 // restarting.
sanghob35a6192015-04-01 13:05:26 -0700530 populateAllRoutingRules();
531 }
532 }
533 }
534}