blob: 9a4ecba4d52bff4b8b7ed1ccc56da8f96a2f2264 [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
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -070018import java.util.Collection;
19import java.util.Collections;
20import java.util.HashMap;
21import java.util.HashSet;
22import java.util.Map;
23import java.util.Set;
24import java.util.stream.Collectors;
25
Jonathan Hartf5829202015-02-12 09:37:02 -080026import org.apache.felix.scr.annotations.Activate;
27import org.apache.felix.scr.annotations.Component;
28import org.apache.felix.scr.annotations.Deactivate;
29import org.apache.felix.scr.annotations.Reference;
30import org.apache.felix.scr.annotations.ReferenceCardinality;
31import org.onlab.packet.Ethernet;
Srikanth Vavilapalli89ad3772015-03-25 18:00:38 -070032import org.onlab.packet.Ip4Address;
33import org.onlab.packet.Ip6Address;
Jonathan Hart7baba072015-02-23 14:27:59 -080034import org.onlab.packet.IpAddress;
35import org.onlab.packet.IpPrefix;
Jonathan Hart54b406b2015-03-06 16:24:14 -080036import org.onlab.packet.MacAddress;
Saurav Dasfbe25c52015-03-04 11:12:00 -080037import org.onlab.packet.VlanId;
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -070038import org.onlab.util.KryoNamespace;
Jonathan Hart54b406b2015-03-06 16:24:14 -080039import org.onosproject.config.NetworkConfigService;
Jonathan Hartf5829202015-02-12 09:37:02 -080040import org.onosproject.core.ApplicationId;
41import org.onosproject.core.CoreService;
42import org.onosproject.net.DeviceId;
alshabib346b5b32015-03-06 00:42:16 -080043import org.onosproject.net.PortNumber;
Jonathan Hartf5829202015-02-12 09:37:02 -080044import org.onosproject.net.flow.DefaultFlowRule;
45import org.onosproject.net.flow.DefaultTrafficSelector;
46import org.onosproject.net.flow.DefaultTrafficTreatment;
47import org.onosproject.net.flow.FlowRule;
Jonathan Hart54b406b2015-03-06 16:24:14 -080048import org.onosproject.net.flow.FlowRule.Type;
alshabib10580802015-02-18 18:30:33 -080049import org.onosproject.net.flow.FlowRuleOperations;
50import org.onosproject.net.flow.FlowRuleOperationsContext;
Jonathan Hartf5829202015-02-12 09:37:02 -080051import org.onosproject.net.flow.FlowRuleService;
52import org.onosproject.net.flow.TrafficSelector;
53import org.onosproject.net.flow.TrafficTreatment;
54import org.onosproject.net.group.DefaultGroupBucket;
55import org.onosproject.net.group.DefaultGroupDescription;
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -070056import org.onosproject.net.group.DefaultGroupKey;
Jonathan Hartf5829202015-02-12 09:37:02 -080057import org.onosproject.net.group.Group;
58import org.onosproject.net.group.GroupBucket;
59import org.onosproject.net.group.GroupBuckets;
60import org.onosproject.net.group.GroupDescription;
Jonathan Hart7baba072015-02-23 14:27:59 -080061import org.onosproject.net.group.GroupEvent;
Jonathan Hart7baba072015-02-23 14:27:59 -080062import org.onosproject.net.group.GroupListener;
Jonathan Hartf5829202015-02-12 09:37:02 -080063import org.onosproject.net.group.GroupService;
Saurav Dasfbe25c52015-03-04 11:12:00 -080064import org.onosproject.net.host.InterfaceIpAddress;
Jonathan Hartf5829202015-02-12 09:37:02 -080065import org.onosproject.net.packet.PacketService;
Jonathan Hart7baba072015-02-23 14:27:59 -080066import org.onosproject.routing.FibEntry;
Jonathan Hart2da1e602015-02-18 19:09:24 -080067import org.onosproject.routing.FibListener;
68import org.onosproject.routing.FibUpdate;
69import org.onosproject.routing.RoutingService;
Saurav Dasfbe25c52015-03-04 11:12:00 -080070import org.onosproject.routing.config.BgpSpeaker;
Jonathan Hart2da1e602015-02-18 19:09:24 -080071import org.onosproject.routing.config.Interface;
72import org.onosproject.routing.config.RoutingConfigurationService;
Jonathan Hartf5829202015-02-12 09:37:02 -080073import org.slf4j.Logger;
74import org.slf4j.LoggerFactory;
75
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -070076import com.google.common.collect.ConcurrentHashMultiset;
77import com.google.common.collect.HashMultimap;
78import com.google.common.collect.Maps;
79import com.google.common.collect.Multimap;
80import com.google.common.collect.Multiset;
Jonathan Hartf5829202015-02-12 09:37:02 -080081
82/**
83 * BgpRouter component.
84 */
85@Component(immediate = true)
86public class BgpRouter {
87
88 private static final Logger log = LoggerFactory.getLogger(BgpRouter.class);
89
90 private static final String BGP_ROUTER_APP = "org.onosproject.bgprouter";
91
Jonathan Hart12ef2052015-03-10 13:58:13 -070092 private static final int PRIORITY_OFFSET = 100;
93 private static final int PRIORITY_MULTIPLIER = 5;
Jonathan Hartf5829202015-02-12 09:37:02 -080094
95 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
96 protected CoreService coreService;
97
98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
99 protected FlowRuleService flowService;
100
101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 protected GroupService groupService;
103
104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
105 protected RoutingService routingService;
106
107 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
108 protected RoutingConfigurationService configService;
109
110 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
111 protected PacketService packetService;
112
Saurav Dasfbe25c52015-03-04 11:12:00 -0800113 //
114 // NOTE: Unused reference - needed to guarantee that the
115 // NetworkConfigReader component is activated and the network configuration
116 // is read.
117 //
118 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
119 protected NetworkConfigService networkConfigService;
120
Jonathan Hartf5829202015-02-12 09:37:02 -0800121 private ApplicationId appId;
122
Jonathan Hart7baba072015-02-23 14:27:59 -0800123 // Reference count for how many times a next hop is used by a route
124 private final Multiset<IpAddress> nextHopsCount = ConcurrentHashMultiset.create();
125
126 // Mapping from prefix to its current next hop
127 private final Map<IpPrefix, IpAddress> prefixToNextHop = Maps.newHashMap();
128
129 // Mapping from next hop IP to next hop object containing group info
130 private final Map<IpAddress, NextHop> nextHops = Maps.newHashMap();
131
132 // Stores FIB updates that are waiting for groups to be set up
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700133 private final Multimap<NextHopGroupKey, FibEntry> pendingUpdates = HashMultimap.create();
Jonathan Hartf5829202015-02-12 09:37:02 -0800134
Saurav Dasfbe25c52015-03-04 11:12:00 -0800135 // Device id of data-plane switch - should be learned from config
136 private DeviceId deviceId;
137
138 // Device id of control-plane switch (OVS) connected to BGP Speaker - should be
139 // learned from config
140 private DeviceId ctrlDeviceId;
Jonathan Hartf5829202015-02-12 09:37:02 -0800141
Jonathan Hart7baba072015-02-23 14:27:59 -0800142 private final GroupListener groupListener = new InternalGroupListener();
143
Jonathan Hartf5829202015-02-12 09:37:02 -0800144 private TunnellingConnectivityManager connectivityManager;
145
sangho5eaf0332015-03-09 15:08:12 -0700146 private IcmpHandler icmpHandler;
147
alshabib10580802015-02-18 18:30:33 -0800148 private InternalTableHandler provisionStaticTables = new InternalTableHandler();
149
Srikanth Vavilapalli89ad3772015-03-25 18:00:38 -0700150 private KryoNamespace appKryo = new KryoNamespace.Builder()
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700151 .register(IpAddress.Version.class)
152 .register(IpAddress.class)
Srikanth Vavilapalli89ad3772015-03-25 18:00:38 -0700153 .register(Ip4Address.class)
154 .register(Ip6Address.class)
155 .register(byte[].class)
156 .register(NextHopGroupKey.class)
157 .build();
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700158
Jonathan Hartf5829202015-02-12 09:37:02 -0800159 @Activate
160 protected void activate() {
Jonathan Hartf5829202015-02-12 09:37:02 -0800161 appId = coreService.registerApplication(BGP_ROUTER_APP);
Saurav Dasfbe25c52015-03-04 11:12:00 -0800162 getDeviceConfiguration(configService.getBgpSpeakers());
Jonathan Hartf5829202015-02-12 09:37:02 -0800163
Jonathan Hart7baba072015-02-23 14:27:59 -0800164 groupService.addListener(groupListener);
165
Saurav Dasfbe25c52015-03-04 11:12:00 -0800166 provisionStaticTables.provision(true, configService.getInterfaces());
alshabib10580802015-02-18 18:30:33 -0800167
Jonathan Hartf5829202015-02-12 09:37:02 -0800168 connectivityManager = new TunnellingConnectivityManager(appId,
169 configService,
Jonathan Hart936a7292015-03-06 18:02:57 -0800170 packetService,
171 flowService);
Jonathan Hartf5829202015-02-12 09:37:02 -0800172
sangho5eaf0332015-03-09 15:08:12 -0700173 icmpHandler = new IcmpHandler(configService, packetService);
174
Pingping Line28ae4c2015-03-13 11:37:03 -0700175 routingService.addFibListener(new InternalFibListener());
176 routingService.start();
Jonathan Hartf5829202015-02-12 09:37:02 -0800177
178 connectivityManager.start();
179
sangho5eaf0332015-03-09 15:08:12 -0700180 icmpHandler.start();
181
Jonathan Hartf5829202015-02-12 09:37:02 -0800182 log.info("BgpRouter started");
183 }
184
185 @Deactivate
186 protected void deactivate() {
187 routingService.stop();
188 connectivityManager.stop();
sangho5eaf0332015-03-09 15:08:12 -0700189 icmpHandler.stop();
Saurav Dasfbe25c52015-03-04 11:12:00 -0800190 provisionStaticTables.provision(false, configService.getInterfaces());
Jonathan Hartf5829202015-02-12 09:37:02 -0800191
Jonathan Hart7baba072015-02-23 14:27:59 -0800192 groupService.removeListener(groupListener);
193
Jonathan Hartf5829202015-02-12 09:37:02 -0800194 log.info("BgpRouter stopped");
195 }
196
Saurav Dasfbe25c52015-03-04 11:12:00 -0800197 private void getDeviceConfiguration(Map<String, BgpSpeaker> bgps) {
198 if (bgps == null || bgps.values().isEmpty()) {
199 log.error("BGP speakers configuration is missing");
200 return;
201 }
202 for (BgpSpeaker s : bgps.values()) {
203 ctrlDeviceId = s.connectPoint().deviceId();
204 if (s.interfaceAddresses() == null || s.interfaceAddresses().isEmpty()) {
205 log.error("BGP Router must have interfaces configured");
206 return;
207 }
208 deviceId = s.interfaceAddresses().get(0).connectPoint().deviceId();
209 break;
210 }
sangho5eaf0332015-03-09 15:08:12 -0700211
Saurav Dasfbe25c52015-03-04 11:12:00 -0800212 log.info("Router dpid: {}", deviceId);
213 log.info("Control Plane OVS dpid: {}", ctrlDeviceId);
214 }
215
Jonathan Hartf5829202015-02-12 09:37:02 -0800216 private void updateFibEntry(Collection<FibUpdate> updates) {
Jonathan Hart5b141422015-03-06 12:59:09 -0800217 Map<FibEntry, Group> toInstall = new HashMap<>(updates.size());
218
Jonathan Hartf5829202015-02-12 09:37:02 -0800219 for (FibUpdate update : updates) {
Jonathan Hart7baba072015-02-23 14:27:59 -0800220 FibEntry entry = update.entry();
Jonathan Hartf5829202015-02-12 09:37:02 -0800221
Jonathan Hart7baba072015-02-23 14:27:59 -0800222 addNextHop(entry);
Jonathan Hartf5829202015-02-12 09:37:02 -0800223
Jonathan Hart7baba072015-02-23 14:27:59 -0800224 Group group;
225 synchronized (pendingUpdates) {
226 NextHop nextHop = nextHops.get(entry.nextHopIp());
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700227 group = groupService.getGroup(deviceId,
228 new DefaultGroupKey(
Srikanth Vavilapalli89ad3772015-03-25 18:00:38 -0700229 appKryo.serialize(nextHop.group())));
Jonathan Hartf5829202015-02-12 09:37:02 -0800230
Jonathan Hart7baba072015-02-23 14:27:59 -0800231 if (group == null) {
232 log.debug("Adding pending flow {}", update.entry());
233 pendingUpdates.put(nextHop.group(), update.entry());
234 continue;
235 }
Jonathan Hartf5829202015-02-12 09:37:02 -0800236 }
237
Jonathan Hart5b141422015-03-06 12:59:09 -0800238 toInstall.put(update.entry(), group);
Jonathan Hartf5829202015-02-12 09:37:02 -0800239 }
Jonathan Hart5b141422015-03-06 12:59:09 -0800240
241 installFlows(toInstall);
Jonathan Hartf5829202015-02-12 09:37:02 -0800242 }
243
Jonathan Hart5b141422015-03-06 12:59:09 -0800244 private void installFlows(Map<FibEntry, Group> entriesToInstall) {
245 FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
Jonathan Hart7baba072015-02-23 14:27:59 -0800246
Jonathan Hart5b141422015-03-06 12:59:09 -0800247 for (Map.Entry<FibEntry, Group> entry : entriesToInstall.entrySet()) {
248 FibEntry fibEntry = entry.getKey();
249 Group group = entry.getValue();
250
251 FlowRule flowRule = generateRibFlowRule(fibEntry.prefix(), group);
252
253 builder.add(flowRule);
254 }
255
256 flowService.apply(builder.build());
Jonathan Hart7baba072015-02-23 14:27:59 -0800257 }
258
259 private synchronized void deleteFibEntry(Collection<FibUpdate> withdraws) {
Jonathan Hart5b141422015-03-06 12:59:09 -0800260 FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
261
Jonathan Hart7baba072015-02-23 14:27:59 -0800262 for (FibUpdate update : withdraws) {
263 FibEntry entry = update.entry();
264
Jonathan Hart37d659c2015-03-08 19:20:38 -0700265 Group group = deleteNextHop(entry.prefix());
266 if (group == null) {
267 log.warn("Group not found when deleting {}", entry);
268 return;
269 }
Jonathan Hartf5829202015-02-12 09:37:02 -0800270
Jonathan Hart37d659c2015-03-08 19:20:38 -0700271 FlowRule flowRule = generateRibFlowRule(entry.prefix(), group);
Jonathan Hartf5829202015-02-12 09:37:02 -0800272
Jonathan Hart5b141422015-03-06 12:59:09 -0800273 builder.remove(flowRule);
Jonathan Hartf5829202015-02-12 09:37:02 -0800274 }
Jonathan Hart5b141422015-03-06 12:59:09 -0800275
276 flowService.apply(builder.build());
Jonathan Hartf5829202015-02-12 09:37:02 -0800277 }
278
Jonathan Hart37d659c2015-03-08 19:20:38 -0700279 private FlowRule generateRibFlowRule(IpPrefix prefix, Group group) {
280 TrafficSelector selector = DefaultTrafficSelector.builder()
281 .matchEthType(Ethernet.TYPE_IPV4)
282 .matchIPDst(prefix)
283 .build();
284
285 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
286 .group(group.id())
287 .build();
288
Jonathan Hart12ef2052015-03-10 13:58:13 -0700289
290 int priority = prefix.prefixLength() * PRIORITY_MULTIPLIER + PRIORITY_OFFSET;
291
Jonathan Hart37d659c2015-03-08 19:20:38 -0700292 return new DefaultFlowRule(deviceId, selector, treatment,
Jonathan Hart12ef2052015-03-10 13:58:13 -0700293 priority, appId, 0, true,
Jonathan Hart37d659c2015-03-08 19:20:38 -0700294 FlowRule.Type.IP);
295 }
296
Jonathan Hart7baba072015-02-23 14:27:59 -0800297 private synchronized void addNextHop(FibEntry entry) {
298 prefixToNextHop.put(entry.prefix(), entry.nextHopIp());
299 if (nextHopsCount.count(entry.nextHopIp()) == 0) {
Jonathan Hartf5829202015-02-12 09:37:02 -0800300 // There was no next hop in the multiset
301
Jonathan Hart7baba072015-02-23 14:27:59 -0800302 Interface egressIntf = configService.getMatchingInterface(entry.nextHopIp());
Jonathan Hartf5829202015-02-12 09:37:02 -0800303 if (egressIntf == null) {
Jonathan Hart7baba072015-02-23 14:27:59 -0800304 log.warn("no egress interface found for {}", entry);
Jonathan Hartf5829202015-02-12 09:37:02 -0800305 return;
306 }
307
Jonathan Hart7baba072015-02-23 14:27:59 -0800308 NextHopGroupKey groupKey = new NextHopGroupKey(entry.nextHopIp());
309
310 NextHop nextHop = new NextHop(entry.nextHopIp(), entry.nextHopMac(), groupKey);
Jonathan Hartf5829202015-02-12 09:37:02 -0800311
312 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
313 .setEthSrc(egressIntf.mac())
314 .setEthDst(nextHop.mac())
Jonathan Hart54b406b2015-03-06 16:24:14 -0800315 .pushVlan()
Jonathan Hartf5829202015-02-12 09:37:02 -0800316 .setVlanId(egressIntf.vlan())
alshabibda1644e2015-03-13 14:01:35 -0700317 .setVlanPcp((byte) 0)
Jonathan Hartf5829202015-02-12 09:37:02 -0800318 .setOutput(egressIntf.connectPoint().port())
319 .build();
320
321 GroupBucket bucket = DefaultGroupBucket.createIndirectGroupBucket(treatment);
322
323 GroupDescription groupDescription
324 = new DefaultGroupDescription(deviceId,
325 GroupDescription.Type.INDIRECT,
326 new GroupBuckets(Collections
Srikanth Vavilapalli89ad3772015-03-25 18:00:38 -0700327 .singletonList(bucket)),
328 new DefaultGroupKey(appKryo.serialize(groupKey)),
Jonathan Hartf5829202015-02-12 09:37:02 -0800329 appId);
330
331 groupService.addGroup(groupDescription);
Jonathan Hart7baba072015-02-23 14:27:59 -0800332
333 nextHops.put(nextHop.ip(), nextHop);
334
Jonathan Hartf5829202015-02-12 09:37:02 -0800335 }
Jonathan Hart7baba072015-02-23 14:27:59 -0800336
337 nextHopsCount.add(entry.nextHopIp());
Jonathan Hartf5829202015-02-12 09:37:02 -0800338 }
339
Jonathan Hart37d659c2015-03-08 19:20:38 -0700340 private synchronized Group deleteNextHop(IpPrefix prefix) {
Jonathan Hart7baba072015-02-23 14:27:59 -0800341 IpAddress nextHopIp = prefixToNextHop.remove(prefix);
342 NextHop nextHop = nextHops.get(nextHopIp);
343 if (nextHop == null) {
344 log.warn("No next hop found when removing prefix {}", prefix);
Jonathan Hart37d659c2015-03-08 19:20:38 -0700345 return null;
Jonathan Hart7baba072015-02-23 14:27:59 -0800346 }
347
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700348 Group group = groupService.getGroup(deviceId,
349 new DefaultGroupKey(appKryo.
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700350 serialize(nextHop.group())));
Jonathan Hart37d659c2015-03-08 19:20:38 -0700351
Jonathan Hartf9f2cbb2015-03-12 17:44:03 -0700352 // FIXME disabling group deletes for now until we verify the logic is OK
353 /*if (nextHopsCount.remove(nextHopIp, 1) <= 1) {
Jonathan Hartf5829202015-02-12 09:37:02 -0800354 // There was one or less next hops, so there are now none
355
Jonathan Hart7baba072015-02-23 14:27:59 -0800356 log.debug("removing group for next hop {}", nextHop);
Jonathan Hartf5829202015-02-12 09:37:02 -0800357
Jonathan Hart7baba072015-02-23 14:27:59 -0800358 nextHops.remove(nextHopIp);
359
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700360 groupService.removeGroup(deviceId,
361 new DefaultGroupKey(appKryo.build().serialize(nextHop.group())),
362 appId);
Jonathan Hartf9f2cbb2015-03-12 17:44:03 -0700363 }*/
Jonathan Hart37d659c2015-03-08 19:20:38 -0700364
365 return group;
Jonathan Hartf5829202015-02-12 09:37:02 -0800366 }
367
368 private class InternalFibListener implements FibListener {
369
370 @Override
371 public void update(Collection<FibUpdate> updates,
372 Collection<FibUpdate> withdraws) {
373 BgpRouter.this.deleteFibEntry(withdraws);
374 BgpRouter.this.updateFibEntry(updates);
375 }
376 }
alshabib10580802015-02-18 18:30:33 -0800377
378 private class InternalTableHandler {
379
380 private static final int CONTROLLER_PRIORITY = 255;
381 private static final int DROP_PRIORITY = 0;
Saurav Dasfbe25c52015-03-04 11:12:00 -0800382 private static final int HIGHEST_PRIORITY = 0xffff;
383 private Set<InterfaceIpAddress> intfIps = new HashSet<InterfaceIpAddress>();
384 private Set<MacAddress> intfMacs = new HashSet<MacAddress>();
alshabib346b5b32015-03-06 00:42:16 -0800385 private Map<PortNumber, VlanId> portVlanPair = Maps.newHashMap();
alshabib10580802015-02-18 18:30:33 -0800386
Saurav Dasfbe25c52015-03-04 11:12:00 -0800387 public void provision(boolean install, Set<Interface> intfs) {
Jonathan Hart5b141422015-03-06 12:59:09 -0800388 getInterfaceConfig(intfs);
alshabib10580802015-02-18 18:30:33 -0800389 processTableZero(install);
390 processTableOne(install);
391 processTableTwo(install);
Saurav Dascbe6de32015-03-01 18:30:46 -0800392 processTableFour(install);
alshabib10580802015-02-18 18:30:33 -0800393 processTableFive(install);
394 processTableSix(install);
395 processTableNine(install);
alshabib10580802015-02-18 18:30:33 -0800396 }
397
Jonathan Hart5b141422015-03-06 12:59:09 -0800398 private void getInterfaceConfig(Set<Interface> intfs) {
Saurav Dasfbe25c52015-03-04 11:12:00 -0800399 log.info("Processing {} router interfaces", intfs.size());
400 for (Interface intf : intfs) {
401 intfIps.addAll(intf.ipAddresses());
402 intfMacs.add(intf.mac());
alshabib346b5b32015-03-06 00:42:16 -0800403 portVlanPair.put(intf.connectPoint().port(), intf.vlan());
Saurav Dasfbe25c52015-03-04 11:12:00 -0800404 }
405 }
406
alshabib10580802015-02-18 18:30:33 -0800407 private void processTableZero(boolean install) {
408 TrafficSelector.Builder selector;
409 TrafficTreatment.Builder treatment;
410
Saurav Dasfbe25c52015-03-04 11:12:00 -0800411 // Bcast rule
alshabib10580802015-02-18 18:30:33 -0800412 selector = DefaultTrafficSelector.builder();
413 treatment = DefaultTrafficTreatment.builder();
414
415 selector.matchEthDst(MacAddress.BROADCAST);
416 treatment.transition(FlowRule.Type.VLAN_MPLS);
417
418 FlowRule rule = new DefaultFlowRule(deviceId, selector.build(),
Jonathan Hart7baba072015-02-23 14:27:59 -0800419 treatment.build(),
420 CONTROLLER_PRIORITY, appId, 0,
Saurav Dascbe6de32015-03-01 18:30:46 -0800421 true, FlowRule.Type.FIRST);
alshabib10580802015-02-18 18:30:33 -0800422
423 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
424
425 ops = install ? ops.add(rule) : ops.remove(rule);
426
Saurav Dasfbe25c52015-03-04 11:12:00 -0800427 // Interface MACs
428 for (MacAddress mac : intfMacs) {
429 log.debug("adding rule for MAC: {}", mac);
430 selector = DefaultTrafficSelector.builder();
431 treatment = DefaultTrafficTreatment.builder();
432
433 selector.matchEthDst(mac);
434 treatment.transition(FlowRule.Type.VLAN_MPLS);
435
436 rule = new DefaultFlowRule(deviceId, selector.build(),
437 treatment.build(),
438 CONTROLLER_PRIORITY, appId, 0,
439 true, FlowRule.Type.FIRST);
440
441 ops = install ? ops.add(rule) : ops.remove(rule);
442 }
443
alshabib10580802015-02-18 18:30:33 -0800444 //Drop rule
445 selector = DefaultTrafficSelector.builder();
446 treatment = DefaultTrafficTreatment.builder();
447
448 treatment.drop();
449
450 rule = new DefaultFlowRule(deviceId, selector.build(),
Jonathan Hart7baba072015-02-23 14:27:59 -0800451 treatment.build(), DROP_PRIORITY, appId,
Saurav Dascbe6de32015-03-01 18:30:46 -0800452 0, true, FlowRule.Type.FIRST);
alshabib10580802015-02-18 18:30:33 -0800453
454 ops = install ? ops.add(rule) : ops.remove(rule);
455
456 flowService.apply(ops.build(new FlowRuleOperationsContext() {
457 @Override
458 public void onSuccess(FlowRuleOperations ops) {
459 log.info("Provisioned default table for bgp router");
460 }
461
462 @Override
463 public void onError(FlowRuleOperations ops) {
464 log.info("Failed to provision default table for bgp router");
465 }
466 }));
467
468 }
469
470 private void processTableOne(boolean install) {
471 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
Jonathan Hart7baba072015-02-23 14:27:59 -0800472 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
473 .builder();
alshabib10580802015-02-18 18:30:33 -0800474 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
475 FlowRule rule;
476
sanghoc0b3c342015-03-12 17:12:10 -0700477 selector.matchVlanId(VlanId.ANY);
alshabib10580802015-02-18 18:30:33 -0800478 treatment.transition(FlowRule.Type.VLAN);
479
480 rule = new DefaultFlowRule(deviceId, selector.build(),
481 treatment.build(), CONTROLLER_PRIORITY,
482 appId, 0, true, FlowRule.Type.VLAN_MPLS);
483
484 ops = install ? ops.add(rule) : ops.remove(rule);
485
alshabib10580802015-02-18 18:30:33 -0800486 flowService.apply(ops.build(new FlowRuleOperationsContext() {
487 @Override
488 public void onSuccess(FlowRuleOperations ops) {
489 log.info("Provisioned vlan/mpls table for bgp router");
490 }
491
492 @Override
493 public void onError(FlowRuleOperations ops) {
Jonathan Hart7baba072015-02-23 14:27:59 -0800494 log.info(
495 "Failed to provision vlan/mpls table for bgp router");
alshabib10580802015-02-18 18:30:33 -0800496 }
497 }));
498
499 }
500
501 private void processTableTwo(boolean install) {
Saurav Dasfbe25c52015-03-04 11:12:00 -0800502 TrafficSelector.Builder selector;
503 TrafficTreatment.Builder treatment;
alshabib10580802015-02-18 18:30:33 -0800504 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
505 FlowRule rule;
506
Saurav Dasfbe25c52015-03-04 11:12:00 -0800507 //Interface Vlans
alshabib346b5b32015-03-06 00:42:16 -0800508 for (Map.Entry<PortNumber, VlanId> portVlan : portVlanPair.entrySet()) {
509 log.debug("adding rule for VLAN: {}", portVlan);
Saurav Dasfbe25c52015-03-04 11:12:00 -0800510 selector = DefaultTrafficSelector.builder();
511 treatment = DefaultTrafficTreatment.builder();
512
alshabib346b5b32015-03-06 00:42:16 -0800513 selector.matchVlanId(portVlan.getValue());
514 selector.matchInPort(portVlan.getKey());
Saurav Dasfbe25c52015-03-04 11:12:00 -0800515 treatment.transition(Type.ETHER);
alshabib346b5b32015-03-06 00:42:16 -0800516 treatment.deferred().popVlan();
Saurav Dasfbe25c52015-03-04 11:12:00 -0800517
518 rule = new DefaultFlowRule(deviceId, selector.build(),
519 treatment.build(), CONTROLLER_PRIORITY, appId,
520 0, true, FlowRule.Type.VLAN);
521
522 ops = install ? ops.add(rule) : ops.remove(rule);
523 }
524
alshabib10580802015-02-18 18:30:33 -0800525 //Drop rule
Saurav Dasfbe25c52015-03-04 11:12:00 -0800526 selector = DefaultTrafficSelector.builder();
527 treatment = DefaultTrafficTreatment.builder();
alshabib10580802015-02-18 18:30:33 -0800528
529 treatment.drop();
530
531 rule = new DefaultFlowRule(deviceId, selector.build(),
Jonathan Hart7baba072015-02-23 14:27:59 -0800532 treatment.build(), DROP_PRIORITY, appId,
533 0, true, FlowRule.Type.VLAN);
alshabib10580802015-02-18 18:30:33 -0800534
535 ops = install ? ops.add(rule) : ops.remove(rule);
536
537 flowService.apply(ops.build(new FlowRuleOperationsContext() {
538 @Override
539 public void onSuccess(FlowRuleOperations ops) {
540 log.info("Provisioned vlan table for bgp router");
541 }
542
543 @Override
544 public void onError(FlowRuleOperations ops) {
545 log.info("Failed to provision vlan table for bgp router");
546 }
547 }));
548 }
549
Saurav Dascbe6de32015-03-01 18:30:46 -0800550 private void processTableFour(boolean install) {
alshabib10580802015-02-18 18:30:33 -0800551 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
Jonathan Hart7baba072015-02-23 14:27:59 -0800552 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
553 .builder();
alshabib10580802015-02-18 18:30:33 -0800554 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
555 FlowRule rule;
556
557 selector.matchEthType(Ethernet.TYPE_ARP);
558 treatment.punt();
559
560 rule = new DefaultFlowRule(deviceId, selector.build(),
561 treatment.build(), CONTROLLER_PRIORITY,
562 appId, 0, true, FlowRule.Type.ETHER);
563
564 ops = install ? ops.add(rule) : ops.remove(rule);
565
566 selector = DefaultTrafficSelector.builder();
567 treatment = DefaultTrafficTreatment.builder();
568
569 selector.matchEthType(Ethernet.TYPE_IPV4);
570 treatment.transition(FlowRule.Type.COS);
571
572 rule = new DefaultFlowRule(deviceId, selector.build(),
573 treatment.build(), CONTROLLER_PRIORITY,
574 appId, 0, true, FlowRule.Type.ETHER);
575
576 ops = install ? ops.add(rule) : ops.remove(rule);
577
578 //Drop rule
579 selector = DefaultTrafficSelector.builder();
580 treatment = DefaultTrafficTreatment.builder();
581
582 treatment.drop();
583
584 rule = new DefaultFlowRule(deviceId, selector.build(),
Jonathan Hart7baba072015-02-23 14:27:59 -0800585 treatment.build(), DROP_PRIORITY, appId,
Saurav Dascbe6de32015-03-01 18:30:46 -0800586 0, true, FlowRule.Type.ETHER);
alshabib10580802015-02-18 18:30:33 -0800587
588 ops = install ? ops.add(rule) : ops.remove(rule);
589
590 flowService.apply(ops.build(new FlowRuleOperationsContext() {
591 @Override
592 public void onSuccess(FlowRuleOperations ops) {
593 log.info("Provisioned ether table for bgp router");
594 }
595
596 @Override
597 public void onError(FlowRuleOperations ops) {
598 log.info("Failed to provision ether table for bgp router");
599 }
600 }));
601
alshabib10580802015-02-18 18:30:33 -0800602 }
603
604 private void processTableFive(boolean install) {
605 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
Jonathan Hart7baba072015-02-23 14:27:59 -0800606 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
607 .builder();
alshabib10580802015-02-18 18:30:33 -0800608 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
609 FlowRule rule;
610
611 treatment.transition(FlowRule.Type.IP);
612
613 rule = new DefaultFlowRule(deviceId, selector.build(),
Jonathan Hart7baba072015-02-23 14:27:59 -0800614 treatment.build(), DROP_PRIORITY, appId,
615 0, true, FlowRule.Type.COS);
alshabib10580802015-02-18 18:30:33 -0800616
617 ops = install ? ops.add(rule) : ops.remove(rule);
618
619 flowService.apply(ops.build(new FlowRuleOperationsContext() {
620 @Override
621 public void onSuccess(FlowRuleOperations ops) {
622 log.info("Provisioned cos table for bgp router");
623 }
624
625 @Override
626 public void onError(FlowRuleOperations ops) {
627 log.info("Failed to provision cos table for bgp router");
628 }
629 }));
630
631 }
632
633 private void processTableSix(boolean install) {
Saurav Dasfbe25c52015-03-04 11:12:00 -0800634 TrafficSelector.Builder selector;
635 TrafficTreatment.Builder treatment;
alshabib10580802015-02-18 18:30:33 -0800636 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
637 FlowRule rule;
638
Saurav Dasfbe25c52015-03-04 11:12:00 -0800639
640 //Interface IPs
641 for (InterfaceIpAddress ipAddr : intfIps) {
642 log.debug("adding rule for IPs: {}", ipAddr.ipAddress());
643 selector = DefaultTrafficSelector.builder();
644 treatment = DefaultTrafficTreatment.builder();
645
646 selector.matchEthType(Ethernet.TYPE_IPV4);
647 selector.matchIPDst(IpPrefix.valueOf(ipAddr.ipAddress(), 32));
648 treatment.transition(Type.ACL);
649
650 rule = new DefaultFlowRule(deviceId, selector.build(),
651 treatment.build(), HIGHEST_PRIORITY, appId,
652 0, true, FlowRule.Type.IP);
653
654 ops = install ? ops.add(rule) : ops.remove(rule);
655 }
656
657
alshabib10580802015-02-18 18:30:33 -0800658 //Drop rule
Saurav Dasfbe25c52015-03-04 11:12:00 -0800659 selector = DefaultTrafficSelector.builder();
660 treatment = DefaultTrafficTreatment.builder();
alshabib10580802015-02-18 18:30:33 -0800661
662 treatment.drop();
663
664 rule = new DefaultFlowRule(deviceId, selector.build(),
Jonathan Hart7baba072015-02-23 14:27:59 -0800665 treatment.build(), DROP_PRIORITY, appId,
666 0, true, FlowRule.Type.IP);
alshabib10580802015-02-18 18:30:33 -0800667
668 ops = install ? ops.add(rule) : ops.remove(rule);
669
670 flowService.apply(ops.build(new FlowRuleOperationsContext() {
671 @Override
672 public void onSuccess(FlowRuleOperations ops) {
673 log.info("Provisioned FIB table for bgp router");
674 }
675
676 @Override
677 public void onError(FlowRuleOperations ops) {
678 log.info("Failed to provision FIB table for bgp router");
679 }
680 }));
681 }
682
683 private void processTableNine(boolean install) {
684 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
Jonathan Hart7baba072015-02-23 14:27:59 -0800685 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
686 .builder();
alshabib10580802015-02-18 18:30:33 -0800687 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
688 FlowRule rule;
689
690 treatment.punt();
691
692 rule = new DefaultFlowRule(deviceId, selector.build(),
693 treatment.build(), CONTROLLER_PRIORITY,
Saurav Dasfa2fa932015-03-03 11:29:48 -0800694 appId, 0, true, FlowRule.Type.DEFAULT);
alshabib10580802015-02-18 18:30:33 -0800695
696 ops = install ? ops.add(rule) : ops.remove(rule);
697
698 flowService.apply(ops.build(new FlowRuleOperationsContext() {
699 @Override
700 public void onSuccess(FlowRuleOperations ops) {
701 log.info("Provisioned Local table for bgp router");
702 }
703
704 @Override
705 public void onError(FlowRuleOperations ops) {
706 log.info("Failed to provision Local table for bgp router");
707 }
708 }));
709 }
Jonathan Hart7baba072015-02-23 14:27:59 -0800710 }
alshabib10580802015-02-18 18:30:33 -0800711
Jonathan Hart7baba072015-02-23 14:27:59 -0800712 private class InternalGroupListener implements GroupListener {
713
714 @Override
715 public void event(GroupEvent event) {
716 Group group = event.subject();
717
718 if (event.type() == GroupEvent.Type.GROUP_ADDED ||
719 event.type() == GroupEvent.Type.GROUP_UPDATED) {
720 synchronized (pendingUpdates) {
Jonathan Hart5b141422015-03-06 12:59:09 -0800721
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700722 NextHopGroupKey nhGroupKey =
Srikanth Vavilapalli89ad3772015-03-25 18:00:38 -0700723 appKryo.deserialize(group.appCookie().key());
Jonathan Hart5b141422015-03-06 12:59:09 -0800724 Map<FibEntry, Group> entriesToInstall =
Srikanth Vavilapalli717361f2015-03-16 12:06:04 -0700725 pendingUpdates.removeAll(nhGroupKey)
Jonathan Hart5b141422015-03-06 12:59:09 -0800726 .stream()
727 .collect(Collectors
728 .toMap(e -> e, e -> group));
729
730 installFlows(entriesToInstall);
Jonathan Hart7baba072015-02-23 14:27:59 -0800731 }
732 }
733 }
alshabib10580802015-02-18 18:30:33 -0800734 }
Jonathan Hartf5829202015-02-12 09:37:02 -0800735}