blob: b85f79fb06ee0ffed4ebce2ce20d1d4073de73fb [file] [log] [blame]
Jonathan Hart6344f572015-12-15 08:26:25 -08001/*
2 * Copyright 2016 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 */
16
17package org.onosproject.routing.impl;
18
Charles Chand0fd5dc2016-02-16 23:14:49 -080019import com.google.common.collect.ImmutableSortedSet;
20import com.google.common.collect.Maps;
Jonathan Hart6344f572015-12-15 08:26:25 -080021import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Component;
23import org.apache.felix.scr.annotations.Deactivate;
24import org.apache.felix.scr.annotations.Reference;
25import org.apache.felix.scr.annotations.ReferenceCardinality;
26import org.onlab.packet.EthType;
Charles Chand0fd5dc2016-02-16 23:14:49 -080027import org.onlab.packet.IpPrefix;
28import org.onlab.packet.MacAddress;
Saurav Das49cb5a12016-01-16 22:54:07 -080029import org.onlab.packet.VlanId;
Jonathan Hart6344f572015-12-15 08:26:25 -080030import org.onosproject.core.ApplicationId;
31import org.onosproject.core.CoreService;
32import org.onosproject.incubator.net.intf.Interface;
33import org.onosproject.incubator.net.intf.InterfaceService;
Charles Chand0fd5dc2016-02-16 23:14:49 -080034import org.onosproject.mastership.MastershipService;
Jonathan Hart6344f572015-12-15 08:26:25 -080035import org.onosproject.net.ConnectPoint;
36import org.onosproject.net.DeviceId;
Charles Chand0fd5dc2016-02-16 23:14:49 -080037import org.onosproject.net.Host;
Jonathan Hart6344f572015-12-15 08:26:25 -080038import org.onosproject.net.PortNumber;
39import org.onosproject.net.config.NetworkConfigEvent;
40import org.onosproject.net.config.NetworkConfigListener;
41import org.onosproject.net.config.NetworkConfigService;
42import org.onosproject.net.device.DeviceEvent;
43import org.onosproject.net.device.DeviceListener;
44import org.onosproject.net.device.DeviceService;
45import org.onosproject.net.flow.DefaultTrafficSelector;
46import org.onosproject.net.flow.DefaultTrafficTreatment;
47import org.onosproject.net.flow.TrafficSelector;
48import org.onosproject.net.flow.TrafficTreatment;
49import org.onosproject.net.flowobjective.DefaultForwardingObjective;
Saurav Das49cb5a12016-01-16 22:54:07 -080050import org.onosproject.net.flowobjective.DefaultNextObjective;
Jonathan Hart6344f572015-12-15 08:26:25 -080051import org.onosproject.net.flowobjective.FlowObjectiveService;
52import org.onosproject.net.flowobjective.ForwardingObjective;
Saurav Das49cb5a12016-01-16 22:54:07 -080053import org.onosproject.net.flowobjective.NextObjective;
Charles Chand0fd5dc2016-02-16 23:14:49 -080054import org.onosproject.net.host.HostEvent;
55import org.onosproject.net.host.HostListener;
56import org.onosproject.net.host.HostService;
Jonathan Hart6344f572015-12-15 08:26:25 -080057import org.onosproject.net.host.InterfaceIpAddress;
58import org.onosproject.routing.RoutingService;
59import org.onosproject.routing.config.RouterConfig;
60import org.slf4j.Logger;
61
Jonathan Hart883fd372016-02-10 14:36:15 -080062import java.util.Collections;
Charles Chand0fd5dc2016-02-16 23:14:49 -080063import java.util.Iterator;
Jonathan Hart883fd372016-02-10 14:36:15 -080064import java.util.List;
Charles Chand0fd5dc2016-02-16 23:14:49 -080065import java.util.Map;
66import java.util.Optional;
67import java.util.Set;
Jonathan Hart883fd372016-02-10 14:36:15 -080068
Jonathan Hart6344f572015-12-15 08:26:25 -080069import static org.slf4j.LoggerFactory.getLogger;
Charles Chand0fd5dc2016-02-16 23:14:49 -080070import static com.google.common.base.Preconditions.checkState;
Jonathan Hart6344f572015-12-15 08:26:25 -080071
72/**
73 * Manages connectivity between peers redirecting control traffic to a routing
74 * control plane available on the dataplane.
75 */
76@Component(immediate = true, enabled = false)
77public class ControlPlaneRedirectManager {
78
79 private final Logger log = getLogger(getClass());
80
Charles Chand0fd5dc2016-02-16 23:14:49 -080081 private static final int MIN_IP_PRIORITY = 10;
82 private static final int ACL_PRIORITY = 40001;
Jonathan Hartea492382016-01-13 09:33:13 -080083 private static final int OSPF_IP_PROTO = 0x59;
Jonathan Hart6344f572015-12-15 08:26:25 -080084
85 private static final String APP_NAME = "org.onosproject.cpredirect";
86 private ApplicationId appId;
87
88 private ConnectPoint controlPlaneConnectPoint;
Jonathan Hartea492382016-01-13 09:33:13 -080089 private boolean ospfEnabled = false;
Jonathan Hart883fd372016-02-10 14:36:15 -080090 private List<String> interfaces = Collections.emptyList();
Charles Chand0fd5dc2016-02-16 23:14:49 -080091 private Map<Host, Set<Integer>> peerNextId = Maps.newConcurrentMap();
Jonathan Hart6344f572015-12-15 08:26:25 -080092
93 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
94 protected CoreService coreService;
95
96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected DeviceService deviceService;
98
99 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
100 protected InterfaceService interfaceService;
101
102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
103 protected FlowObjectiveService flowObjectiveService;
104
105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
106 protected NetworkConfigService networkConfigService;
107
Charles Chand0fd5dc2016-02-16 23:14:49 -0800108 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
109 protected MastershipService mastershipService;
110
111 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
112 protected HostService hostService;
113
Jonathan Hart6344f572015-12-15 08:26:25 -0800114 private final InternalDeviceListener deviceListener = new InternalDeviceListener();
115 private final InternalNetworkConfigListener networkConfigListener =
116 new InternalNetworkConfigListener();
Charles Chand0fd5dc2016-02-16 23:14:49 -0800117 private final InternalHostListener hostListener = new InternalHostListener();
Jonathan Hart6344f572015-12-15 08:26:25 -0800118
119 @Activate
120 public void activate() {
121 this.appId = coreService.registerApplication(APP_NAME);
122
123 deviceService.addListener(deviceListener);
124 networkConfigService.addListener(networkConfigListener);
Charles Chand0fd5dc2016-02-16 23:14:49 -0800125 hostService.addListener(hostListener);
Jonathan Hart6344f572015-12-15 08:26:25 -0800126
127 updateConfig();
128 }
129
130 @Deactivate
131 public void deactivate() {
132 deviceService.removeListener(deviceListener);
133 networkConfigService.removeListener(networkConfigListener);
Charles Chand0fd5dc2016-02-16 23:14:49 -0800134 hostService.removeListener(hostListener);
Jonathan Hart6344f572015-12-15 08:26:25 -0800135 }
136
137 private void updateConfig() {
138 ApplicationId routingAppId =
139 coreService.registerApplication(RoutingService.ROUTER_APP_ID);
140
141 RouterConfig config = networkConfigService.getConfig(
142 routingAppId, RoutingService.ROUTER_CONFIG_CLASS);
143
144 if (config == null) {
Saurav Das49cb5a12016-01-16 22:54:07 -0800145 log.warn("Router config not available");
Jonathan Hart6344f572015-12-15 08:26:25 -0800146 return;
147 }
148
Jonathan Hartea492382016-01-13 09:33:13 -0800149 controlPlaneConnectPoint = config.getControlPlaneConnectPoint();
150 ospfEnabled = config.getOspfEnabled();
Jonathan Hart883fd372016-02-10 14:36:15 -0800151 interfaces = config.getInterfaces();
Jonathan Hart6344f572015-12-15 08:26:25 -0800152
Jonathan Hartea492382016-01-13 09:33:13 -0800153 updateDevice();
154 }
155
156 private void updateDevice() {
Jonathan Hart6344f572015-12-15 08:26:25 -0800157 if (controlPlaneConnectPoint != null &&
158 deviceService.isAvailable(controlPlaneConnectPoint.deviceId())) {
Jonathan Hartea492382016-01-13 09:33:13 -0800159 DeviceId deviceId = controlPlaneConnectPoint.deviceId();
160
161 interfaceService.getInterfaces().stream()
162 .filter(intf -> intf.connectPoint().deviceId().equals(deviceId))
Jonathan Hart883fd372016-02-10 14:36:15 -0800163 .filter(intf -> interfaces.isEmpty() || interfaces.contains(intf.name()))
Jonathan Hartea492382016-01-13 09:33:13 -0800164 .forEach(this::provisionInterface);
165
166 log.info("Set up interfaces on {}", controlPlaneConnectPoint.deviceId());
Jonathan Hart6344f572015-12-15 08:26:25 -0800167 }
168 }
169
Jonathan Hartea492382016-01-13 09:33:13 -0800170 private void provisionInterface(Interface intf) {
171 addBasicInterfaceForwarding(intf);
172 updateOspfForwarding(intf);
Jonathan Hart6344f572015-12-15 08:26:25 -0800173 }
174
Jonathan Hartea492382016-01-13 09:33:13 -0800175 private void addBasicInterfaceForwarding(Interface intf) {
Jonathan Hart6344f572015-12-15 08:26:25 -0800176 log.debug("Adding interface objectives for {}", intf);
177
178 DeviceId deviceId = controlPlaneConnectPoint.deviceId();
179 PortNumber controlPlanePort = controlPlaneConnectPoint.port();
180
181 for (InterfaceIpAddress ip : intf.ipAddresses()) {
Saurav Das49cb5a12016-01-16 22:54:07 -0800182 // create nextObjectives for forwarding to this interface and the
183 // controlPlaneConnectPoint
184 int cpNextId, intfNextId;
185 if (intf.vlan() == VlanId.NONE) {
186 cpNextId = createNextObjective(deviceId, controlPlanePort,
187 VlanId.vlanId(SingleSwitchFibInstaller.ASSIGNED_VLAN),
188 true);
189 intfNextId = createNextObjective(deviceId, intf.connectPoint().port(),
190 VlanId.vlanId(SingleSwitchFibInstaller.ASSIGNED_VLAN),
191 true);
192 } else {
193 cpNextId = createNextObjective(deviceId, controlPlanePort,
194 intf.vlan(), false);
195 intfNextId = createNextObjective(deviceId, intf.connectPoint().port(),
196 intf.vlan(), false);
197 }
198
Jonathan Hart6344f572015-12-15 08:26:25 -0800199 // IPv4 to router
200 TrafficSelector toSelector = DefaultTrafficSelector.builder()
201 .matchInPort(intf.connectPoint().port())
202 .matchEthDst(intf.mac())
203 .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
204 .matchVlanId(intf.vlan())
205 .matchIPDst(ip.ipAddress().toIpPrefix())
206 .build();
207
Jonathan Hart6344f572015-12-15 08:26:25 -0800208 flowObjectiveService.forward(deviceId,
Saurav Das49cb5a12016-01-16 22:54:07 -0800209 buildForwardingObjective(toSelector, null, cpNextId, true));
Jonathan Hart6344f572015-12-15 08:26:25 -0800210
211 // IPv4 from router
212 TrafficSelector fromSelector = DefaultTrafficSelector.builder()
213 .matchInPort(controlPlanePort)
214 .matchEthSrc(intf.mac())
215 .matchVlanId(intf.vlan())
216 .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
217 .matchIPSrc(ip.ipAddress().toIpPrefix())
218 .build();
219
Jonathan Hart6344f572015-12-15 08:26:25 -0800220 flowObjectiveService.forward(deviceId,
Saurav Das49cb5a12016-01-16 22:54:07 -0800221 buildForwardingObjective(fromSelector, null, intfNextId, true));
Jonathan Hart6344f572015-12-15 08:26:25 -0800222
223 // ARP to router
224 toSelector = DefaultTrafficSelector.builder()
225 .matchInPort(intf.connectPoint().port())
226 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
227 .matchVlanId(intf.vlan())
228 .build();
229
Saurav Das49cb5a12016-01-16 22:54:07 -0800230 TrafficTreatment puntTreatment = DefaultTrafficTreatment.builder()
Jonathan Hart6344f572015-12-15 08:26:25 -0800231 .punt()
232 .build();
233
234 flowObjectiveService.forward(deviceId,
Saurav Das49cb5a12016-01-16 22:54:07 -0800235 buildForwardingObjective(toSelector, puntTreatment, cpNextId, true));
Jonathan Hart6344f572015-12-15 08:26:25 -0800236
237 // ARP from router
238 fromSelector = DefaultTrafficSelector.builder()
239 .matchInPort(controlPlanePort)
240 .matchEthSrc(intf.mac())
241 .matchVlanId(intf.vlan())
242 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
Saurav Das49cb5a12016-01-16 22:54:07 -0800243 .matchArpSpa(ip.ipAddress().getIp4Address())
Jonathan Hart6344f572015-12-15 08:26:25 -0800244 .build();
245
246 flowObjectiveService.forward(deviceId,
Saurav Das49cb5a12016-01-16 22:54:07 -0800247 buildForwardingObjective(fromSelector, puntTreatment, intfNextId, true));
Jonathan Hart6344f572015-12-15 08:26:25 -0800248 }
249 }
250
Jonathan Hartea492382016-01-13 09:33:13 -0800251 private void updateOspfForwarding(Interface intf) {
252 // OSPF to router
253 TrafficSelector toSelector = DefaultTrafficSelector.builder()
254 .matchInPort(intf.connectPoint().port())
255 .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
256 .matchVlanId(intf.vlan())
257 .matchIPProtocol((byte) OSPF_IP_PROTO)
258 .build();
Jonathan Hart6344f572015-12-15 08:26:25 -0800259
Saurav Das49cb5a12016-01-16 22:54:07 -0800260 // create nextObjectives for forwarding to the controlPlaneConnectPoint
261 DeviceId deviceId = controlPlaneConnectPoint.deviceId();
262 PortNumber controlPlanePort = controlPlaneConnectPoint.port();
263 int cpNextId;
264 if (intf.vlan() == VlanId.NONE) {
265 cpNextId = createNextObjective(deviceId, controlPlanePort,
266 VlanId.vlanId(SingleSwitchFibInstaller.ASSIGNED_VLAN),
267 true);
268 } else {
269 cpNextId = createNextObjective(deviceId, controlPlanePort,
270 intf.vlan(), false);
271 }
272 log.debug("ospf flows intf:{} nextid:{}", intf, cpNextId);
Jonathan Hartea492382016-01-13 09:33:13 -0800273 flowObjectiveService.forward(controlPlaneConnectPoint.deviceId(),
Saurav Das49cb5a12016-01-16 22:54:07 -0800274 buildForwardingObjective(toSelector, null, cpNextId, ospfEnabled));
Jonathan Hartea492382016-01-13 09:33:13 -0800275 }
276
277 /**
Saurav Das49cb5a12016-01-16 22:54:07 -0800278 * Creates a next objective for forwarding to a port. Handles metadata for
279 * some pipelines that require vlan information for egress port.
280 *
281 * @param deviceId the device on which the next objective is being created
282 * @param portNumber the egress port
283 * @param vlanId vlan information for egress port
284 * @param popVlan if vlan tag should be popped or not
285 * @return nextId of the next objective created
286 */
287 private int createNextObjective(DeviceId deviceId, PortNumber portNumber,
288 VlanId vlanId, boolean popVlan) {
289 int nextId = flowObjectiveService.allocateNextId();
290 NextObjective.Builder nextObjBuilder = DefaultNextObjective
291 .builder().withId(nextId)
292 .withType(NextObjective.Type.SIMPLE)
293 .fromApp(appId);
294
295 TrafficTreatment.Builder ttBuilder = DefaultTrafficTreatment.builder();
296 if (popVlan) {
297 ttBuilder.popVlan();
298 }
299 ttBuilder.setOutput(portNumber);
300
301 // setup metadata to pass to nextObjective - indicate the vlan on egress
302 // if needed by the switch pipeline.
303 TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder();
304 metabuilder.matchVlanId(vlanId);
305
306 nextObjBuilder.withMeta(metabuilder.build());
307 nextObjBuilder.addTreatment(ttBuilder.build());
308 log.debug("Submited next objective {} in device {} for port/vlan {}/{}",
309 nextId, deviceId, portNumber, vlanId);
310 flowObjectiveService.next(deviceId, nextObjBuilder.add());
311 return nextId;
312 }
313
314 /**
315 * Builds a forwarding objective from the given selector, treatment and nextId.
Jonathan Hartea492382016-01-13 09:33:13 -0800316 *
317 * @param selector selector
Saurav Das49cb5a12016-01-16 22:54:07 -0800318 * @param treatment treatment to apply to packet, can be null
319 * @param nextId next objective to point to for forwarding packet
Jonathan Hartea492382016-01-13 09:33:13 -0800320 * @param add true to create an add objective, false to create a remove
321 * objective
322 * @return forwarding objective
323 */
324 private ForwardingObjective buildForwardingObjective(TrafficSelector selector,
325 TrafficTreatment treatment,
Saurav Das49cb5a12016-01-16 22:54:07 -0800326 int nextId,
Jonathan Hartea492382016-01-13 09:33:13 -0800327 boolean add) {
Saurav Das49cb5a12016-01-16 22:54:07 -0800328 DefaultForwardingObjective.Builder fobBuilder = DefaultForwardingObjective.builder();
329 fobBuilder.withSelector(selector);
330 if (treatment != null) {
331 fobBuilder.withTreatment(treatment);
332 }
333 if (nextId != -1) {
334 fobBuilder.nextStep(nextId);
335 }
336 fobBuilder.fromApp(appId)
Charles Chand0fd5dc2016-02-16 23:14:49 -0800337 .withPriority(ACL_PRIORITY)
Saurav Das49cb5a12016-01-16 22:54:07 -0800338 .withFlag(ForwardingObjective.Flag.VERSATILE);
Jonathan Hartea492382016-01-13 09:33:13 -0800339
340 return add ? fobBuilder.add() : fobBuilder.remove();
Jonathan Hart6344f572015-12-15 08:26:25 -0800341 }
342
Jonathan Hartea492382016-01-13 09:33:13 -0800343 /**
344 * Listener for device events.
345 */
Jonathan Hart6344f572015-12-15 08:26:25 -0800346 private class InternalDeviceListener implements DeviceListener {
347 @Override
348 public void event(DeviceEvent event) {
349 if (controlPlaneConnectPoint != null &&
350 event.subject().id().equals(controlPlaneConnectPoint.deviceId())) {
351 switch (event.type()) {
352 case DEVICE_ADDED:
353 case DEVICE_AVAILABILITY_CHANGED:
354 if (deviceService.isAvailable(event.subject().id())) {
355 log.info("Device connected {}", event.subject().id());
Jonathan Hartea492382016-01-13 09:33:13 -0800356 updateDevice();
Jonathan Hart6344f572015-12-15 08:26:25 -0800357 }
358
359 break;
360 case DEVICE_UPDATED:
361 case DEVICE_REMOVED:
362 case DEVICE_SUSPENDED:
363 case PORT_ADDED:
364 case PORT_UPDATED:
365 case PORT_REMOVED:
366 default:
367 break;
368 }
369 }
370 }
371 }
372
Jonathan Hartea492382016-01-13 09:33:13 -0800373 /**
374 * Listener for network config events.
375 */
Jonathan Hart6344f572015-12-15 08:26:25 -0800376 private class InternalNetworkConfigListener implements NetworkConfigListener {
377 @Override
378 public void event(NetworkConfigEvent event) {
Jonathan Hartea492382016-01-13 09:33:13 -0800379 if (event.configClass().equals(RoutingService.ROUTER_CONFIG_CLASS)) {
Jonathan Hart6344f572015-12-15 08:26:25 -0800380 switch (event.type()) {
381 case CONFIG_ADDED:
382 case CONFIG_UPDATED:
383 updateConfig();
384 break;
385 case CONFIG_REGISTERED:
386 case CONFIG_UNREGISTERED:
387 case CONFIG_REMOVED:
388 default:
389 break;
390 }
391 }
392 }
393 }
Charles Chand0fd5dc2016-02-16 23:14:49 -0800394
395 /**
396 * Listener for host events.
397 */
398 private class InternalHostListener implements HostListener {
399 private void peerAdded(HostEvent event) {
400 Host peer = event.subject();
401 Optional<Interface> peerIntf =
402 interfaceService.getInterfacesByPort(peer.location()).stream()
403 .filter(intf -> interfaces.isEmpty() || interfaces.contains(intf.name()))
404 .filter(intf -> peer.vlan().equals(intf.vlan()))
405 .findFirst();
406 if (!peerIntf.isPresent()) {
407 log.debug("Adding peer {}/{} on {} but the interface is not configured",
408 peer.mac(), peer.vlan(), peer.location());
409 return;
410 }
411
412 // Generate L3 Unicast groups and store it in the map
413 int toRouterL3Unicast = createPeerGroup(peer.mac(), peerIntf.get().mac(),
414 peer.vlan(), peer.location().deviceId(), controlPlaneConnectPoint.port());
415 int toPeerL3Unicast = createPeerGroup(peerIntf.get().mac(), peer.mac(),
416 peer.vlan(), peer.location().deviceId(), peer.location().port());
417 peerNextId.put(peer, ImmutableSortedSet.of(toRouterL3Unicast, toPeerL3Unicast));
418
419 // From peer to router
420 peerIntf.get().ipAddresses().forEach(routerIp -> {
421 flowObjectiveService.forward(peer.location().deviceId(),
422 createPeerObjBuilder(toRouterL3Unicast, routerIp.ipAddress().toIpPrefix()).add());
423 });
424
425 // From router to peer
426 peer.ipAddresses().forEach(peerIp -> {
427 flowObjectiveService.forward(peer.location().deviceId(),
428 createPeerObjBuilder(toPeerL3Unicast, peerIp.toIpPrefix()).add());
429 });
430 }
431
432 private void peerRemoved(HostEvent event) {
433 Host peer = event.subject();
434 Optional<Interface> peerIntf =
435 interfaceService.getInterfacesByPort(peer.location()).stream()
436 .filter(intf -> interfaces.isEmpty() || interfaces.contains(intf.name()))
437 .filter(intf -> peer.vlan().equals(intf.vlan()))
438 .findFirst();
439 if (!peerIntf.isPresent()) {
440 log.debug("Removing peer {}/{} on {} but the interface is not configured",
441 peer.mac(), peer.vlan(), peer.location());
442 return;
443 }
444
445 Set<Integer> nextIds = peerNextId.get(peer);
446 checkState(peerNextId.get(peer) != null,
447 "Peer nextId should not be null");
448 checkState(peerNextId.get(peer).size() == 2,
449 "Wrong nextId associated with the peer");
450 Iterator<Integer> iter = peerNextId.get(peer).iterator();
451 int toRouterL3Unicast = iter.next();
452 int toPeerL3Unicast = iter.next();
453
454 // From peer to router
455 peerIntf.get().ipAddresses().forEach(routerIp -> {
456 flowObjectiveService.forward(peer.location().deviceId(),
457 createPeerObjBuilder(toRouterL3Unicast, routerIp.ipAddress().toIpPrefix()).remove());
458 });
459
460 // From router to peer
461 peer.ipAddresses().forEach(peerIp -> {
462 flowObjectiveService.forward(peer.location().deviceId(),
463 createPeerObjBuilder(toPeerL3Unicast, peerIp.toIpPrefix()).remove());
464 });
465 }
466
467 private ForwardingObjective.Builder createPeerObjBuilder(
468 int nextId, IpPrefix ipAddresses) {
469 TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
470 sbuilder.matchEthType(EthType.EtherType.IPV4.ethType().toShort());
471 sbuilder.matchIPDst(ipAddresses);
472 DefaultForwardingObjective.Builder builder =
473 DefaultForwardingObjective.builder()
474 .withSelector(sbuilder.build())
475 .fromApp(appId)
476 .withPriority(getPriorityFromPrefix(ipAddresses))
477 .withFlag(ForwardingObjective.Flag.SPECIFIC);
478 if (nextId != -1) {
479 builder.nextStep(nextId);
480 }
481 return builder;
482 }
483
484 private int createPeerGroup(MacAddress srcMac, MacAddress dstMac,
485 VlanId vlanId, DeviceId deviceId, PortNumber port) {
486 int nextId = flowObjectiveService.allocateNextId();
487 NextObjective.Builder nextObjBuilder = DefaultNextObjective.builder()
488 .withId(nextId)
489 .withType(NextObjective.Type.SIMPLE)
490 .fromApp(appId);
491
492 TrafficTreatment.Builder ttBuilder = DefaultTrafficTreatment.builder();
493 ttBuilder.setEthSrc(srcMac);
494 ttBuilder.setEthDst(dstMac);
495 ttBuilder.setOutput(port);
496 nextObjBuilder.addTreatment(ttBuilder.build());
497
498 TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder();
499 VlanId matchVlanId = (vlanId.equals(VlanId.NONE)) ?
500 VlanId.vlanId(SingleSwitchFibInstaller.ASSIGNED_VLAN) :
501 vlanId;
502 metabuilder.matchVlanId(matchVlanId);
503 nextObjBuilder.withMeta(metabuilder.build());
504
505 flowObjectiveService.next(deviceId, nextObjBuilder.add());
506 return nextId;
507 }
508
509 @Override
510 public void event(HostEvent event) {
511 DeviceId deviceId = event.subject().location().deviceId();
512 if (!mastershipService.isLocalMaster(deviceId)) {
513 return;
514 }
515 switch (event.type()) {
516 case HOST_ADDED:
517 peerAdded(event);
518 break;
519 case HOST_MOVED:
520 //TODO We assume BGP peer does not move for now
521 break;
522 case HOST_REMOVED:
523 peerRemoved(event);
524 break;
525 case HOST_UPDATED:
526 //TODO We assume BGP peer does not change IP for now
527 break;
528 default:
529 break;
530 }
531 }
532 }
533
534 private int getPriorityFromPrefix(IpPrefix prefix) {
535 return (prefix.isIp4()) ?
536 2000 * prefix.prefixLength() + MIN_IP_PRIORITY :
537 500 * prefix.prefixLength() + MIN_IP_PRIORITY;
538 }
Jonathan Hart6344f572015-12-15 08:26:25 -0800539}