blob: 62098b484c9ea8df522a08786014a3cfc4db0780 [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
18import com.google.common.collect.ConcurrentHashMultiset;
19import com.google.common.collect.Multiset;
20import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
23import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
25import org.onlab.packet.Ethernet;
alshabib10580802015-02-18 18:30:33 -080026import org.onlab.packet.MacAddress;
Jonathan Hartf5829202015-02-12 09:37:02 -080027import org.onosproject.core.ApplicationId;
28import org.onosproject.core.CoreService;
29import org.onosproject.net.DeviceId;
30import org.onosproject.net.flow.DefaultFlowRule;
31import org.onosproject.net.flow.DefaultTrafficSelector;
32import org.onosproject.net.flow.DefaultTrafficTreatment;
33import org.onosproject.net.flow.FlowRule;
alshabib10580802015-02-18 18:30:33 -080034import org.onosproject.net.flow.FlowRuleOperations;
35import org.onosproject.net.flow.FlowRuleOperationsContext;
Jonathan Hartf5829202015-02-12 09:37:02 -080036import org.onosproject.net.flow.FlowRuleService;
37import org.onosproject.net.flow.TrafficSelector;
38import org.onosproject.net.flow.TrafficTreatment;
39import org.onosproject.net.group.DefaultGroupBucket;
40import org.onosproject.net.group.DefaultGroupDescription;
41import org.onosproject.net.group.Group;
42import org.onosproject.net.group.GroupBucket;
43import org.onosproject.net.group.GroupBuckets;
44import org.onosproject.net.group.GroupDescription;
45import org.onosproject.net.group.GroupKey;
46import org.onosproject.net.group.GroupService;
47import org.onosproject.net.packet.PacketService;
Jonathan Hart2da1e602015-02-18 19:09:24 -080048import org.onosproject.routing.FibListener;
49import org.onosproject.routing.FibUpdate;
50import org.onosproject.routing.RoutingService;
51import org.onosproject.routing.config.Interface;
52import org.onosproject.routing.config.RoutingConfigurationService;
Jonathan Hartf5829202015-02-12 09:37:02 -080053import org.slf4j.Logger;
54import org.slf4j.LoggerFactory;
55
56import java.util.Collection;
57import java.util.Collections;
58import java.util.HashMap;
59import java.util.Map;
60
61/**
62 * BgpRouter component.
63 */
64@Component(immediate = true)
65public class BgpRouter {
66
67 private static final Logger log = LoggerFactory.getLogger(BgpRouter.class);
68
69 private static final String BGP_ROUTER_APP = "org.onosproject.bgprouter";
70
71 private static final int PRIORITY = 1;
72
73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 protected CoreService coreService;
75
76 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected FlowRuleService flowService;
78
79 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 protected GroupService groupService;
81
82 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 protected RoutingService routingService;
84
85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 protected RoutingConfigurationService configService;
87
88 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
89 protected PacketService packetService;
90
91 private ApplicationId appId;
92
93 private final Multiset<NextHop> nextHops = ConcurrentHashMultiset.create();
94 private final Map<NextHop, NextHopGroupKey> groups = new HashMap<>();
95
alshabib10580802015-02-18 18:30:33 -080096 private DeviceId deviceId = DeviceId.deviceId("of:0000000000000001"); // TODO config
Jonathan Hartf5829202015-02-12 09:37:02 -080097
98 private TunnellingConnectivityManager connectivityManager;
99
alshabib10580802015-02-18 18:30:33 -0800100 private InternalTableHandler provisionStaticTables = new InternalTableHandler();
101
Jonathan Hartf5829202015-02-12 09:37:02 -0800102 @Activate
103 protected void activate() {
104 log.info("Bgp1Router started");
105 appId = coreService.registerApplication(BGP_ROUTER_APP);
106
alshabib10580802015-02-18 18:30:33 -0800107 provisionStaticTables.provision(true);
108
Jonathan Hartf5829202015-02-12 09:37:02 -0800109 connectivityManager = new TunnellingConnectivityManager(appId,
110 configService,
111 packetService);
112
113 routingService.start(new InternalFibListener());
114
115 connectivityManager.start();
116
117 log.info("BgpRouter started");
118 }
119
120 @Deactivate
121 protected void deactivate() {
122 routingService.stop();
123 connectivityManager.stop();
alshabib10580802015-02-18 18:30:33 -0800124 provisionStaticTables.provision(false);
Jonathan Hartf5829202015-02-12 09:37:02 -0800125
126 log.info("BgpRouter stopped");
127 }
128
129 private void updateFibEntry(Collection<FibUpdate> updates) {
130 for (FibUpdate update : updates) {
131 NextHop nextHop = new NextHop(update.entry().nextHopIp(),
132 update.entry().nextHopMac());
133
134 addNextHop(nextHop);
135
136 TrafficSelector selector = DefaultTrafficSelector.builder()
137 .matchEthType(Ethernet.TYPE_IPV4)
138 .matchIPDst(update.entry().prefix())
139 .build();
140
141 // TODO ensure group exists
142 NextHopGroupKey groupKey = groups.get(nextHop);
143 Group group = groupService.getGroup(deviceId, groupKey);
144 if (group == null) {
145 // TODO handle this
146 log.warn("oops, group {} wasn't there");
147 continue;
148 }
149
150 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
151 .group(group.id())
152 .build();
153
154 FlowRule flowRule = new DefaultFlowRule(deviceId, selector, treatment,
155 PRIORITY, appId, 0, true,
156 FlowRule.Type.IP);
157
158 flowService.applyFlowRules(flowRule);
159 }
160 }
161
162 private void deleteFibEntry(Collection<FibUpdate> withdraws) {
163 for (FibUpdate update : withdraws) {
164 NextHop nextHop = new NextHop(update.entry().nextHopIp(),
165 update.entry().nextHopMac());
166
167 deleteNextHop(nextHop);
168
169 TrafficSelector selector = DefaultTrafficSelector.builder()
170 .matchIPDst(update.entry().prefix())
171 .build();
172
173 FlowRule flowRule = new DefaultFlowRule(deviceId, selector, null,
174 PRIORITY, appId, 0, true,
175 FlowRule.Type.IP);
176
177 flowService.removeFlowRules(flowRule);
178 }
179 }
180
181 private void addNextHop(NextHop nextHop) {
182 if (nextHops.add(nextHop, 1) == 0) {
183 // There was no next hop in the multiset
184
185 Interface egressIntf = configService.getMatchingInterface(nextHop.ip());
186 if (egressIntf == null) {
187 log.warn("no egress interface found for {}", nextHop);
188 return;
189 }
190
191 NextHopGroupKey groupKey = new NextHopGroupKey(nextHop.ip());
192 groups.put(nextHop, groupKey);
193
194 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
195 .setEthSrc(egressIntf.mac())
196 .setEthDst(nextHop.mac())
197 .setVlanId(egressIntf.vlan())
198 .setOutput(egressIntf.connectPoint().port())
199 .build();
200
201 GroupBucket bucket = DefaultGroupBucket.createIndirectGroupBucket(treatment);
202
203 GroupDescription groupDescription
204 = new DefaultGroupDescription(deviceId,
205 GroupDescription.Type.INDIRECT,
206 new GroupBuckets(Collections
207 .singletonList(bucket)),
208 groupKey,
209 appId);
210
211 groupService.addGroup(groupDescription);
212 }
213 }
214
215 private void deleteNextHop(NextHop nextHop) {
216 if (nextHops.remove(nextHop, 1) <= 1) {
217 // There was one or less next hops, so there are now none
218
219 log.debug("removing group");
220
221 GroupKey groupKey = groups.remove(nextHop);
222 groupService.removeGroup(deviceId, groupKey, appId);
223 }
224 }
225
226 private class InternalFibListener implements FibListener {
227
228 @Override
229 public void update(Collection<FibUpdate> updates,
230 Collection<FibUpdate> withdraws) {
231 BgpRouter.this.deleteFibEntry(withdraws);
232 BgpRouter.this.updateFibEntry(updates);
233 }
234 }
alshabib10580802015-02-18 18:30:33 -0800235
236 private class InternalTableHandler {
237
238 private static final int CONTROLLER_PRIORITY = 255;
239 private static final int DROP_PRIORITY = 0;
240
241
242 public void provision(boolean install) {
243
244 processTableZero(install);
245 processTableOne(install);
246 processTableTwo(install);
247 processTableThree(install);
248 processTableFive(install);
249 processTableSix(install);
250 processTableNine(install);
251
252 }
253
254 private void processTableZero(boolean install) {
255 TrafficSelector.Builder selector;
256 TrafficTreatment.Builder treatment;
257
258 selector = DefaultTrafficSelector.builder();
259 treatment = DefaultTrafficTreatment.builder();
260
261 selector.matchEthDst(MacAddress.BROADCAST);
262 treatment.transition(FlowRule.Type.VLAN_MPLS);
263
264 FlowRule rule = new DefaultFlowRule(deviceId, selector.build(),
265 treatment.build(), CONTROLLER_PRIORITY,
266 appId, 0, true);
267
268 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
269
270 ops = install ? ops.add(rule) : ops.remove(rule);
271
272
273 //Drop rule
274 selector = DefaultTrafficSelector.builder();
275 treatment = DefaultTrafficTreatment.builder();
276
277 treatment.drop();
278
279 rule = new DefaultFlowRule(deviceId, selector.build(),
280 treatment.build(), DROP_PRIORITY,
281 appId, 0, true, FlowRule.Type.VLAN_MPLS);
282
283 ops = install ? ops.add(rule) : ops.remove(rule);
284
285 flowService.apply(ops.build(new FlowRuleOperationsContext() {
286 @Override
287 public void onSuccess(FlowRuleOperations ops) {
288 log.info("Provisioned default table for bgp router");
289 }
290
291 @Override
292 public void onError(FlowRuleOperations ops) {
293 log.info("Failed to provision default table for bgp router");
294 }
295 }));
296
297 }
298
299 private void processTableOne(boolean install) {
300 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
301 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
302 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
303 FlowRule rule;
304
305 selector.matchEthType(Ethernet.TYPE_IPV4);
306 treatment.transition(FlowRule.Type.VLAN);
307
308 rule = new DefaultFlowRule(deviceId, selector.build(),
309 treatment.build(), CONTROLLER_PRIORITY,
310 appId, 0, true, FlowRule.Type.VLAN_MPLS);
311
312 ops = install ? ops.add(rule) : ops.remove(rule);
313
314 selector = DefaultTrafficSelector.builder();
315 treatment = DefaultTrafficTreatment.builder();
316
317 selector.matchEthType(Ethernet.TYPE_ARP);
318 treatment.transition(FlowRule.Type.VLAN);
319
320 rule = new DefaultFlowRule(deviceId, selector.build(),
321 treatment.build(), CONTROLLER_PRIORITY,
322 appId, 0, true, FlowRule.Type.VLAN_MPLS);
323
324 ops = install ? ops.add(rule) : ops.remove(rule);
325
326 selector = DefaultTrafficSelector.builder();
327 treatment = DefaultTrafficTreatment.builder();
328
329 selector.matchEthType(Ethernet.TYPE_VLAN);
330 treatment.transition(FlowRule.Type.VLAN);
331
332 rule = new DefaultFlowRule(deviceId, selector.build(),
333 treatment.build(), CONTROLLER_PRIORITY,
334 appId, 0, true, FlowRule.Type.VLAN_MPLS);
335
336 ops = install ? ops.add(rule) : ops.remove(rule);
337
338 //Drop rule
339 selector = DefaultTrafficSelector.builder();
340 treatment = DefaultTrafficTreatment.builder();
341
342 treatment.drop();
343
344 rule = new DefaultFlowRule(deviceId, selector.build(),
345 treatment.build(), DROP_PRIORITY,
346 appId, 0, true, FlowRule.Type.VLAN_MPLS);
347
348 ops = install ? ops.add(rule) : ops.remove(rule);
349
350 flowService.apply(ops.build(new FlowRuleOperationsContext() {
351 @Override
352 public void onSuccess(FlowRuleOperations ops) {
353 log.info("Provisioned vlan/mpls table for bgp router");
354 }
355
356 @Override
357 public void onError(FlowRuleOperations ops) {
358 log.info("Failed to provision vlan/mpls table for bgp router");
359 }
360 }));
361
362 }
363
364 private void processTableTwo(boolean install) {
365 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
366 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
367 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
368 FlowRule rule;
369
370 //Drop rule
371
372 treatment.drop();
373
374 rule = new DefaultFlowRule(deviceId, selector.build(),
375 treatment.build(), DROP_PRIORITY,
376 appId, 0, true, FlowRule.Type.VLAN);
377
378 ops = install ? ops.add(rule) : ops.remove(rule);
379
380 flowService.apply(ops.build(new FlowRuleOperationsContext() {
381 @Override
382 public void onSuccess(FlowRuleOperations ops) {
383 log.info("Provisioned vlan table for bgp router");
384 }
385
386 @Override
387 public void onError(FlowRuleOperations ops) {
388 log.info("Failed to provision vlan table for bgp router");
389 }
390 }));
391 }
392
393
394
395 private void processTableThree(boolean install) {
396 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
397 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
398 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
399 FlowRule rule;
400
401 selector.matchEthType(Ethernet.TYPE_ARP);
402 treatment.punt();
403
404 rule = new DefaultFlowRule(deviceId, selector.build(),
405 treatment.build(), CONTROLLER_PRIORITY,
406 appId, 0, true, FlowRule.Type.ETHER);
407
408 ops = install ? ops.add(rule) : ops.remove(rule);
409
410 selector = DefaultTrafficSelector.builder();
411 treatment = DefaultTrafficTreatment.builder();
412
413 selector.matchEthType(Ethernet.TYPE_IPV4);
414 treatment.transition(FlowRule.Type.COS);
415
416 rule = new DefaultFlowRule(deviceId, selector.build(),
417 treatment.build(), CONTROLLER_PRIORITY,
418 appId, 0, true, FlowRule.Type.ETHER);
419
420 ops = install ? ops.add(rule) : ops.remove(rule);
421
422 //Drop rule
423 selector = DefaultTrafficSelector.builder();
424 treatment = DefaultTrafficTreatment.builder();
425
426 treatment.drop();
427
428 rule = new DefaultFlowRule(deviceId, selector.build(),
429 treatment.build(), DROP_PRIORITY,
430 appId, 0, true, FlowRule.Type.VLAN_MPLS);
431
432 ops = install ? ops.add(rule) : ops.remove(rule);
433
434 flowService.apply(ops.build(new FlowRuleOperationsContext() {
435 @Override
436 public void onSuccess(FlowRuleOperations ops) {
437 log.info("Provisioned ether table for bgp router");
438 }
439
440 @Override
441 public void onError(FlowRuleOperations ops) {
442 log.info("Failed to provision ether table for bgp router");
443 }
444 }));
445
446
447 }
448
449 private void processTableFive(boolean install) {
450 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
451 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
452 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
453 FlowRule rule;
454
455 treatment.transition(FlowRule.Type.IP);
456
457 rule = new DefaultFlowRule(deviceId, selector.build(),
458 treatment.build(), DROP_PRIORITY,
459 appId, 0, true, FlowRule.Type.COS);
460
461 ops = install ? ops.add(rule) : ops.remove(rule);
462
463 flowService.apply(ops.build(new FlowRuleOperationsContext() {
464 @Override
465 public void onSuccess(FlowRuleOperations ops) {
466 log.info("Provisioned cos table for bgp router");
467 }
468
469 @Override
470 public void onError(FlowRuleOperations ops) {
471 log.info("Failed to provision cos table for bgp router");
472 }
473 }));
474
475 }
476
477 private void processTableSix(boolean install) {
478 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
479 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
480 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
481 FlowRule rule;
482
483 //Drop rule
484
485 treatment.drop();
486
487 rule = new DefaultFlowRule(deviceId, selector.build(),
488 treatment.build(), DROP_PRIORITY,
489 appId, 0, true, FlowRule.Type.IP);
490
491 ops = install ? ops.add(rule) : ops.remove(rule);
492
493 flowService.apply(ops.build(new FlowRuleOperationsContext() {
494 @Override
495 public void onSuccess(FlowRuleOperations ops) {
496 log.info("Provisioned FIB table for bgp router");
497 }
498
499 @Override
500 public void onError(FlowRuleOperations ops) {
501 log.info("Failed to provision FIB table for bgp router");
502 }
503 }));
504 }
505
506 private void processTableNine(boolean install) {
507 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
508 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
509 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
510 FlowRule rule;
511
512 treatment.punt();
513
514 rule = new DefaultFlowRule(deviceId, selector.build(),
515 treatment.build(), CONTROLLER_PRIORITY,
516 appId, 0, true, FlowRule.Type.ACL);
517
518 ops = install ? ops.add(rule) : ops.remove(rule);
519
520 flowService.apply(ops.build(new FlowRuleOperationsContext() {
521 @Override
522 public void onSuccess(FlowRuleOperations ops) {
523 log.info("Provisioned Local table for bgp router");
524 }
525
526 @Override
527 public void onError(FlowRuleOperations ops) {
528 log.info("Failed to provision Local table for bgp router");
529 }
530 }));
531 }
532
533 }
Jonathan Hartf5829202015-02-12 09:37:02 -0800534}