blob: 58e796fb04d03079efa5c8df5ff21397ef7156c3 [file] [log] [blame]
Jonathan Hartf5829202015-02-12 09:37:02 -08001/*
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.bgprouter;
17
alshabib910aff12015-04-09 16:55:57 -070018import com.google.common.collect.ConcurrentHashMultiset;
19import com.google.common.collect.HashMultimap;
20import com.google.common.collect.Maps;
21import com.google.common.collect.Multimap;
22import com.google.common.collect.Multiset;
Jonathan Hartf5829202015-02-12 09:37:02 -080023import org.apache.felix.scr.annotations.Activate;
24import org.apache.felix.scr.annotations.Component;
25import org.apache.felix.scr.annotations.Deactivate;
26import org.apache.felix.scr.annotations.Reference;
27import org.apache.felix.scr.annotations.ReferenceCardinality;
28import org.onlab.packet.Ethernet;
Srikanth Vavilapalli89ad3772015-03-25 18:00:38 -070029import org.onlab.packet.Ip4Address;
30import org.onlab.packet.Ip6Address;
Jonathan Hart7baba072015-02-23 14:27:59 -080031import org.onlab.packet.IpAddress;
32import org.onlab.packet.IpPrefix;
Jonathan Hart54b406b2015-03-06 16:24:14 -080033import org.onlab.packet.MacAddress;
Saurav Dasfbe25c52015-03-04 11:12:00 -080034import org.onlab.packet.VlanId;
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -070035import org.onlab.util.KryoNamespace;
Jonathan Hart54b406b2015-03-06 16:24:14 -080036import org.onosproject.config.NetworkConfigService;
Jonathan Hartf5829202015-02-12 09:37:02 -080037import org.onosproject.core.ApplicationId;
38import org.onosproject.core.CoreService;
39import org.onosproject.net.DeviceId;
alshabib346b5b32015-03-06 00:42:16 -080040import org.onosproject.net.PortNumber;
Jonathan Hartf5829202015-02-12 09:37:02 -080041import org.onosproject.net.flow.DefaultFlowRule;
42import org.onosproject.net.flow.DefaultTrafficSelector;
43import org.onosproject.net.flow.DefaultTrafficTreatment;
44import org.onosproject.net.flow.FlowRule;
alshabib10580802015-02-18 18:30:33 -080045import org.onosproject.net.flow.FlowRuleOperations;
Jonathan Hartf5829202015-02-12 09:37:02 -080046import org.onosproject.net.flow.FlowRuleService;
47import org.onosproject.net.flow.TrafficSelector;
48import org.onosproject.net.flow.TrafficTreatment;
alshabib910aff12015-04-09 16:55:57 -070049import org.onosproject.net.flow.criteria.Criteria;
50import org.onosproject.net.flowobjective.DefaultFilteringObjective;
51import org.onosproject.net.flowobjective.FilteringObjective;
52import org.onosproject.net.flowobjective.FlowObjectiveService;
Jonathan Hartf5829202015-02-12 09:37:02 -080053import org.onosproject.net.group.DefaultGroupBucket;
54import org.onosproject.net.group.DefaultGroupDescription;
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -070055import org.onosproject.net.group.DefaultGroupKey;
Jonathan Hartf5829202015-02-12 09:37:02 -080056import org.onosproject.net.group.Group;
57import org.onosproject.net.group.GroupBucket;
58import org.onosproject.net.group.GroupBuckets;
59import org.onosproject.net.group.GroupDescription;
Jonathan Hart7baba072015-02-23 14:27:59 -080060import org.onosproject.net.group.GroupEvent;
Jonathan Hart7baba072015-02-23 14:27:59 -080061import org.onosproject.net.group.GroupListener;
Jonathan Hartf5829202015-02-12 09:37:02 -080062import org.onosproject.net.group.GroupService;
Saurav Dasfbe25c52015-03-04 11:12:00 -080063import org.onosproject.net.host.InterfaceIpAddress;
Jonathan Hartf5829202015-02-12 09:37:02 -080064import org.onosproject.net.packet.PacketService;
Jonathan Hart7baba072015-02-23 14:27:59 -080065import org.onosproject.routing.FibEntry;
Jonathan Hart2da1e602015-02-18 19:09:24 -080066import org.onosproject.routing.FibListener;
67import org.onosproject.routing.FibUpdate;
68import org.onosproject.routing.RoutingService;
Saurav Dasfbe25c52015-03-04 11:12:00 -080069import org.onosproject.routing.config.BgpSpeaker;
Jonathan Hart2da1e602015-02-18 19:09:24 -080070import org.onosproject.routing.config.Interface;
71import org.onosproject.routing.config.RoutingConfigurationService;
Jonathan Hartf5829202015-02-12 09:37:02 -080072import org.slf4j.Logger;
73import org.slf4j.LoggerFactory;
74
alshabib910aff12015-04-09 16:55:57 -070075import java.util.Collection;
76import java.util.Collections;
77import java.util.HashMap;
78import java.util.HashSet;
79import java.util.Map;
80import java.util.Set;
81import java.util.stream.Collectors;
Jonathan Hartf5829202015-02-12 09:37:02 -080082
83/**
84 * BgpRouter component.
85 */
86@Component(immediate = true)
87public class BgpRouter {
88
89 private static final Logger log = LoggerFactory.getLogger(BgpRouter.class);
90
91 private static final String BGP_ROUTER_APP = "org.onosproject.bgprouter";
92
Jonathan Hart12ef2052015-03-10 13:58:13 -070093 private static final int PRIORITY_OFFSET = 100;
94 private static final int PRIORITY_MULTIPLIER = 5;
Jonathan Hartf5829202015-02-12 09:37:02 -080095
96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected CoreService coreService;
98
99 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
100 protected FlowRuleService flowService;
101
102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 protected GroupService groupService;
104
105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
106 protected RoutingService routingService;
107
108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
109 protected RoutingConfigurationService configService;
110
111 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
112 protected PacketService packetService;
113
Saurav Dasfbe25c52015-03-04 11:12:00 -0800114 //
115 // NOTE: Unused reference - needed to guarantee that the
116 // NetworkConfigReader component is activated and the network configuration
117 // is read.
118 //
119 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
120 protected NetworkConfigService networkConfigService;
121
Jonathan Hartf5829202015-02-12 09:37:02 -0800122 private ApplicationId appId;
123
Jonathan Hart7baba072015-02-23 14:27:59 -0800124 // Reference count for how many times a next hop is used by a route
125 private final Multiset<IpAddress> nextHopsCount = ConcurrentHashMultiset.create();
126
127 // Mapping from prefix to its current next hop
128 private final Map<IpPrefix, IpAddress> prefixToNextHop = Maps.newHashMap();
129
130 // Mapping from next hop IP to next hop object containing group info
131 private final Map<IpAddress, NextHop> nextHops = Maps.newHashMap();
132
133 // Stores FIB updates that are waiting for groups to be set up
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700134 private final Multimap<NextHopGroupKey, FibEntry> pendingUpdates = HashMultimap.create();
Jonathan Hartf5829202015-02-12 09:37:02 -0800135
Saurav Dasfbe25c52015-03-04 11:12:00 -0800136 // Device id of data-plane switch - should be learned from config
137 private DeviceId deviceId;
138
139 // Device id of control-plane switch (OVS) connected to BGP Speaker - should be
140 // learned from config
141 private DeviceId ctrlDeviceId;
Jonathan Hartf5829202015-02-12 09:37:02 -0800142
Jonathan Hart7baba072015-02-23 14:27:59 -0800143 private final GroupListener groupListener = new InternalGroupListener();
144
Jonathan Hartf5829202015-02-12 09:37:02 -0800145 private TunnellingConnectivityManager connectivityManager;
146
sangho5eaf0332015-03-09 15:08:12 -0700147 private IcmpHandler icmpHandler;
148
alshabib10580802015-02-18 18:30:33 -0800149 private InternalTableHandler provisionStaticTables = new InternalTableHandler();
150
Srikanth Vavilapalli89ad3772015-03-25 18:00:38 -0700151 private KryoNamespace appKryo = new KryoNamespace.Builder()
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700152 .register(IpAddress.Version.class)
153 .register(IpAddress.class)
Srikanth Vavilapalli89ad3772015-03-25 18:00:38 -0700154 .register(Ip4Address.class)
155 .register(Ip6Address.class)
156 .register(byte[].class)
157 .register(NextHopGroupKey.class)
158 .build();
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700159
alshabib910aff12015-04-09 16:55:57 -0700160
161 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
162 protected FlowObjectiveService flowObjectiveService;
163
Jonathan Hartf5829202015-02-12 09:37:02 -0800164 @Activate
165 protected void activate() {
Jonathan Hartf5829202015-02-12 09:37:02 -0800166 appId = coreService.registerApplication(BGP_ROUTER_APP);
Saurav Dasfbe25c52015-03-04 11:12:00 -0800167 getDeviceConfiguration(configService.getBgpSpeakers());
Jonathan Hartf5829202015-02-12 09:37:02 -0800168
Jonathan Hart7baba072015-02-23 14:27:59 -0800169 groupService.addListener(groupListener);
170
Saurav Dasfbe25c52015-03-04 11:12:00 -0800171 provisionStaticTables.provision(true, configService.getInterfaces());
alshabib10580802015-02-18 18:30:33 -0800172
Jonathan Hartf5829202015-02-12 09:37:02 -0800173 connectivityManager = new TunnellingConnectivityManager(appId,
174 configService,
Jonathan Hart936a7292015-03-06 18:02:57 -0800175 packetService,
176 flowService);
Jonathan Hartf5829202015-02-12 09:37:02 -0800177
sangho5eaf0332015-03-09 15:08:12 -0700178 icmpHandler = new IcmpHandler(configService, packetService);
179
Pingping Line28ae4c2015-03-13 11:37:03 -0700180 routingService.addFibListener(new InternalFibListener());
181 routingService.start();
Jonathan Hartf5829202015-02-12 09:37:02 -0800182
183 connectivityManager.start();
184
sangho5eaf0332015-03-09 15:08:12 -0700185 icmpHandler.start();
186
Jonathan Hartf5829202015-02-12 09:37:02 -0800187 log.info("BgpRouter started");
188 }
189
190 @Deactivate
191 protected void deactivate() {
192 routingService.stop();
193 connectivityManager.stop();
sangho5eaf0332015-03-09 15:08:12 -0700194 icmpHandler.stop();
Saurav Dasfbe25c52015-03-04 11:12:00 -0800195 provisionStaticTables.provision(false, configService.getInterfaces());
Jonathan Hartf5829202015-02-12 09:37:02 -0800196
Jonathan Hart7baba072015-02-23 14:27:59 -0800197 groupService.removeListener(groupListener);
198
Jonathan Hartf5829202015-02-12 09:37:02 -0800199 log.info("BgpRouter stopped");
200 }
201
Saurav Dasfbe25c52015-03-04 11:12:00 -0800202 private void getDeviceConfiguration(Map<String, BgpSpeaker> bgps) {
203 if (bgps == null || bgps.values().isEmpty()) {
204 log.error("BGP speakers configuration is missing");
205 return;
206 }
207 for (BgpSpeaker s : bgps.values()) {
208 ctrlDeviceId = s.connectPoint().deviceId();
209 if (s.interfaceAddresses() == null || s.interfaceAddresses().isEmpty()) {
210 log.error("BGP Router must have interfaces configured");
211 return;
212 }
213 deviceId = s.interfaceAddresses().get(0).connectPoint().deviceId();
214 break;
215 }
sangho5eaf0332015-03-09 15:08:12 -0700216
Saurav Dasfbe25c52015-03-04 11:12:00 -0800217 log.info("Router dpid: {}", deviceId);
218 log.info("Control Plane OVS dpid: {}", ctrlDeviceId);
219 }
220
Jonathan Hartf5829202015-02-12 09:37:02 -0800221 private void updateFibEntry(Collection<FibUpdate> updates) {
Jonathan Hart5b141422015-03-06 12:59:09 -0800222 Map<FibEntry, Group> toInstall = new HashMap<>(updates.size());
223
Jonathan Hartf5829202015-02-12 09:37:02 -0800224 for (FibUpdate update : updates) {
Jonathan Hart7baba072015-02-23 14:27:59 -0800225 FibEntry entry = update.entry();
Jonathan Hartf5829202015-02-12 09:37:02 -0800226
Jonathan Hart7baba072015-02-23 14:27:59 -0800227 addNextHop(entry);
Jonathan Hartf5829202015-02-12 09:37:02 -0800228
Jonathan Hart7baba072015-02-23 14:27:59 -0800229 Group group;
230 synchronized (pendingUpdates) {
231 NextHop nextHop = nextHops.get(entry.nextHopIp());
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700232 group = groupService.getGroup(deviceId,
233 new DefaultGroupKey(
Srikanth Vavilapalli89ad3772015-03-25 18:00:38 -0700234 appKryo.serialize(nextHop.group())));
Jonathan Hartf5829202015-02-12 09:37:02 -0800235
Jonathan Hart7baba072015-02-23 14:27:59 -0800236 if (group == null) {
237 log.debug("Adding pending flow {}", update.entry());
238 pendingUpdates.put(nextHop.group(), update.entry());
239 continue;
240 }
Jonathan Hartf5829202015-02-12 09:37:02 -0800241 }
242
Jonathan Hart5b141422015-03-06 12:59:09 -0800243 toInstall.put(update.entry(), group);
Jonathan Hartf5829202015-02-12 09:37:02 -0800244 }
Jonathan Hart5b141422015-03-06 12:59:09 -0800245
246 installFlows(toInstall);
Jonathan Hartf5829202015-02-12 09:37:02 -0800247 }
248
Jonathan Hart5b141422015-03-06 12:59:09 -0800249 private void installFlows(Map<FibEntry, Group> entriesToInstall) {
250 FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
Jonathan Hart7baba072015-02-23 14:27:59 -0800251
Jonathan Hart5b141422015-03-06 12:59:09 -0800252 for (Map.Entry<FibEntry, Group> entry : entriesToInstall.entrySet()) {
253 FibEntry fibEntry = entry.getKey();
254 Group group = entry.getValue();
255
256 FlowRule flowRule = generateRibFlowRule(fibEntry.prefix(), group);
257
258 builder.add(flowRule);
259 }
260
261 flowService.apply(builder.build());
Jonathan Hart7baba072015-02-23 14:27:59 -0800262 }
263
264 private synchronized void deleteFibEntry(Collection<FibUpdate> withdraws) {
Jonathan Hart5b141422015-03-06 12:59:09 -0800265 FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
266
Jonathan Hart7baba072015-02-23 14:27:59 -0800267 for (FibUpdate update : withdraws) {
268 FibEntry entry = update.entry();
269
Jonathan Hart37d659c2015-03-08 19:20:38 -0700270 Group group = deleteNextHop(entry.prefix());
271 if (group == null) {
272 log.warn("Group not found when deleting {}", entry);
273 return;
274 }
Jonathan Hartf5829202015-02-12 09:37:02 -0800275
Jonathan Hart37d659c2015-03-08 19:20:38 -0700276 FlowRule flowRule = generateRibFlowRule(entry.prefix(), group);
Jonathan Hartf5829202015-02-12 09:37:02 -0800277
Jonathan Hart5b141422015-03-06 12:59:09 -0800278 builder.remove(flowRule);
Jonathan Hartf5829202015-02-12 09:37:02 -0800279 }
Jonathan Hart5b141422015-03-06 12:59:09 -0800280
281 flowService.apply(builder.build());
Jonathan Hartf5829202015-02-12 09:37:02 -0800282 }
283
Jonathan Hart37d659c2015-03-08 19:20:38 -0700284 private FlowRule generateRibFlowRule(IpPrefix prefix, Group group) {
285 TrafficSelector selector = DefaultTrafficSelector.builder()
286 .matchEthType(Ethernet.TYPE_IPV4)
287 .matchIPDst(prefix)
288 .build();
289
290 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
291 .group(group.id())
292 .build();
293
Jonathan Hart12ef2052015-03-10 13:58:13 -0700294
295 int priority = prefix.prefixLength() * PRIORITY_MULTIPLIER + PRIORITY_OFFSET;
296
Jonathan Hart37d659c2015-03-08 19:20:38 -0700297 return new DefaultFlowRule(deviceId, selector, treatment,
Jonathan Hart12ef2052015-03-10 13:58:13 -0700298 priority, appId, 0, true,
Jonathan Hart37d659c2015-03-08 19:20:38 -0700299 FlowRule.Type.IP);
300 }
301
Jonathan Hart7baba072015-02-23 14:27:59 -0800302 private synchronized void addNextHop(FibEntry entry) {
303 prefixToNextHop.put(entry.prefix(), entry.nextHopIp());
304 if (nextHopsCount.count(entry.nextHopIp()) == 0) {
Jonathan Hartf5829202015-02-12 09:37:02 -0800305 // There was no next hop in the multiset
306
Jonathan Hart7baba072015-02-23 14:27:59 -0800307 Interface egressIntf = configService.getMatchingInterface(entry.nextHopIp());
Jonathan Hartf5829202015-02-12 09:37:02 -0800308 if (egressIntf == null) {
Jonathan Hart7baba072015-02-23 14:27:59 -0800309 log.warn("no egress interface found for {}", entry);
Jonathan Hartf5829202015-02-12 09:37:02 -0800310 return;
311 }
312
Jonathan Hart7baba072015-02-23 14:27:59 -0800313 NextHopGroupKey groupKey = new NextHopGroupKey(entry.nextHopIp());
314
315 NextHop nextHop = new NextHop(entry.nextHopIp(), entry.nextHopMac(), groupKey);
Jonathan Hartf5829202015-02-12 09:37:02 -0800316
317 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
318 .setEthSrc(egressIntf.mac())
319 .setEthDst(nextHop.mac())
Jonathan Hart54b406b2015-03-06 16:24:14 -0800320 .pushVlan()
Jonathan Hartf5829202015-02-12 09:37:02 -0800321 .setVlanId(egressIntf.vlan())
alshabibda1644e2015-03-13 14:01:35 -0700322 .setVlanPcp((byte) 0)
Jonathan Hartf5829202015-02-12 09:37:02 -0800323 .setOutput(egressIntf.connectPoint().port())
324 .build();
325
326 GroupBucket bucket = DefaultGroupBucket.createIndirectGroupBucket(treatment);
327
328 GroupDescription groupDescription
329 = new DefaultGroupDescription(deviceId,
330 GroupDescription.Type.INDIRECT,
331 new GroupBuckets(Collections
Srikanth Vavilapalli89ad3772015-03-25 18:00:38 -0700332 .singletonList(bucket)),
333 new DefaultGroupKey(appKryo.serialize(groupKey)),
Jonathan Hartf5829202015-02-12 09:37:02 -0800334 appId);
335
336 groupService.addGroup(groupDescription);
Jonathan Hart7baba072015-02-23 14:27:59 -0800337
338 nextHops.put(nextHop.ip(), nextHop);
339
Jonathan Hartf5829202015-02-12 09:37:02 -0800340 }
Jonathan Hart7baba072015-02-23 14:27:59 -0800341
342 nextHopsCount.add(entry.nextHopIp());
Jonathan Hartf5829202015-02-12 09:37:02 -0800343 }
344
Jonathan Hart37d659c2015-03-08 19:20:38 -0700345 private synchronized Group deleteNextHop(IpPrefix prefix) {
Jonathan Hart7baba072015-02-23 14:27:59 -0800346 IpAddress nextHopIp = prefixToNextHop.remove(prefix);
347 NextHop nextHop = nextHops.get(nextHopIp);
348 if (nextHop == null) {
349 log.warn("No next hop found when removing prefix {}", prefix);
Jonathan Hart37d659c2015-03-08 19:20:38 -0700350 return null;
Jonathan Hart7baba072015-02-23 14:27:59 -0800351 }
352
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700353 Group group = groupService.getGroup(deviceId,
354 new DefaultGroupKey(appKryo.
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700355 serialize(nextHop.group())));
Jonathan Hart37d659c2015-03-08 19:20:38 -0700356
Jonathan Hartf9f2cbb2015-03-12 17:44:03 -0700357 // FIXME disabling group deletes for now until we verify the logic is OK
358 /*if (nextHopsCount.remove(nextHopIp, 1) <= 1) {
Jonathan Hartf5829202015-02-12 09:37:02 -0800359 // There was one or less next hops, so there are now none
360
Jonathan Hart7baba072015-02-23 14:27:59 -0800361 log.debug("removing group for next hop {}", nextHop);
Jonathan Hartf5829202015-02-12 09:37:02 -0800362
Jonathan Hart7baba072015-02-23 14:27:59 -0800363 nextHops.remove(nextHopIp);
364
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700365 groupService.removeGroup(deviceId,
366 new DefaultGroupKey(appKryo.build().serialize(nextHop.group())),
367 appId);
Jonathan Hartf9f2cbb2015-03-12 17:44:03 -0700368 }*/
Jonathan Hart37d659c2015-03-08 19:20:38 -0700369
370 return group;
Jonathan Hartf5829202015-02-12 09:37:02 -0800371 }
372
373 private class InternalFibListener implements FibListener {
374
375 @Override
376 public void update(Collection<FibUpdate> updates,
377 Collection<FibUpdate> withdraws) {
378 BgpRouter.this.deleteFibEntry(withdraws);
379 BgpRouter.this.updateFibEntry(updates);
380 }
381 }
alshabib10580802015-02-18 18:30:33 -0800382
383 private class InternalTableHandler {
384
Saurav Dasfbe25c52015-03-04 11:12:00 -0800385 private Set<InterfaceIpAddress> intfIps = new HashSet<InterfaceIpAddress>();
386 private Set<MacAddress> intfMacs = new HashSet<MacAddress>();
alshabib346b5b32015-03-06 00:42:16 -0800387 private Map<PortNumber, VlanId> portVlanPair = Maps.newHashMap();
alshabib10580802015-02-18 18:30:33 -0800388
Saurav Dasfbe25c52015-03-04 11:12:00 -0800389 public void provision(boolean install, Set<Interface> intfs) {
Jonathan Hart5b141422015-03-06 12:59:09 -0800390 getInterfaceConfig(intfs);
alshabib10580802015-02-18 18:30:33 -0800391 }
392
Jonathan Hart5b141422015-03-06 12:59:09 -0800393 private void getInterfaceConfig(Set<Interface> intfs) {
Saurav Dasfbe25c52015-03-04 11:12:00 -0800394 log.info("Processing {} router interfaces", intfs.size());
395 for (Interface intf : intfs) {
alshabib910aff12015-04-09 16:55:57 -0700396 FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
397 flowObjectiveService.filter(deviceId, Collections.singletonList(
398 fob.addCondition(Criteria.matchEthDst(intf.mac()))
399 .fromApp(appId).permit().add()));
Saurav Dasfbe25c52015-03-04 11:12:00 -0800400 intfIps.addAll(intf.ipAddresses());
401 intfMacs.add(intf.mac());
alshabib346b5b32015-03-06 00:42:16 -0800402 portVlanPair.put(intf.connectPoint().port(), intf.vlan());
Saurav Dasfbe25c52015-03-04 11:12:00 -0800403 }
404 }
405
alshabib10580802015-02-18 18:30:33 -0800406
Jonathan Hart7baba072015-02-23 14:27:59 -0800407 }
alshabib10580802015-02-18 18:30:33 -0800408
Jonathan Hart7baba072015-02-23 14:27:59 -0800409 private class InternalGroupListener implements GroupListener {
410
411 @Override
412 public void event(GroupEvent event) {
413 Group group = event.subject();
414
415 if (event.type() == GroupEvent.Type.GROUP_ADDED ||
416 event.type() == GroupEvent.Type.GROUP_UPDATED) {
417 synchronized (pendingUpdates) {
Jonathan Hart5b141422015-03-06 12:59:09 -0800418
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700419 NextHopGroupKey nhGroupKey =
Srikanth Vavilapalli89ad3772015-03-25 18:00:38 -0700420 appKryo.deserialize(group.appCookie().key());
Jonathan Hart5b141422015-03-06 12:59:09 -0800421 Map<FibEntry, Group> entriesToInstall =
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700422 pendingUpdates.removeAll(nhGroupKey)
Jonathan Hart5b141422015-03-06 12:59:09 -0800423 .stream()
424 .collect(Collectors
425 .toMap(e -> e, e -> group));
426
427 installFlows(entriesToInstall);
Jonathan Hart7baba072015-02-23 14:27:59 -0800428 }
429 }
430 }
alshabib10580802015-02-18 18:30:33 -0800431 }
Jonathan Hartf5829202015-02-12 09:37:02 -0800432}