blob: b004ee787a64b7ad37b49859755ba5e7e1d59297 [file] [log] [blame]
Hyunsun Moon44aac662017-02-18 02:07:01 +09001/*
2 * Copyright 2016-present 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.openstacknetworking.impl;
17
18import com.google.common.base.Strings;
19import com.google.common.collect.ImmutableSet;
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;
26import org.onlab.packet.IPv4;
27import org.onlab.packet.IpAddress;
28import org.onlab.packet.IpPrefix;
daniel parkee8700b2017-05-11 15:50:03 +090029import org.onlab.packet.MacAddress;
30import org.onlab.packet.VlanId;
Hyunsun Moon44aac662017-02-18 02:07:01 +090031import org.onosproject.cluster.ClusterService;
32import org.onosproject.cluster.LeadershipService;
33import org.onosproject.cluster.NodeId;
34import org.onosproject.core.ApplicationId;
35import org.onosproject.core.CoreService;
36import org.onosproject.core.GroupId;
37import org.onosproject.net.DeviceId;
38import org.onosproject.net.PortNumber;
daniel parkee8700b2017-05-11 15:50:03 +090039import org.onosproject.net.device.DeviceService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090040import org.onosproject.net.flow.DefaultTrafficSelector;
41import org.onosproject.net.flow.DefaultTrafficTreatment;
42import org.onosproject.net.flow.TrafficSelector;
43import org.onosproject.net.flow.TrafficTreatment;
44import org.onosproject.net.flowobjective.FlowObjectiveService;
45import org.onosproject.net.flowobjective.ForwardingObjective;
46import org.onosproject.openstacknetworking.api.Constants;
47import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
48import org.onosproject.openstacknetworking.api.OpenstackRouterEvent;
49import org.onosproject.openstacknetworking.api.OpenstackRouterListener;
50import org.onosproject.openstacknetworking.api.OpenstackRouterService;
51import org.onosproject.openstacknode.OpenstackNode;
52import org.onosproject.openstacknode.OpenstackNodeEvent;
53import org.onosproject.openstacknode.OpenstackNodeListener;
54import org.onosproject.openstacknode.OpenstackNodeService;
daniel parkee8700b2017-05-11 15:50:03 +090055import org.onosproject.openstacknode.OpenstackNodeService.NetworkMode;
56
Hyunsun Moon44aac662017-02-18 02:07:01 +090057import org.openstack4j.model.network.ExternalGateway;
58import org.openstack4j.model.network.Network;
daniel parkee8700b2017-05-11 15:50:03 +090059import org.openstack4j.model.network.NetworkType;
Hyunsun Moon44aac662017-02-18 02:07:01 +090060import org.openstack4j.model.network.Router;
61import org.openstack4j.model.network.RouterInterface;
62import org.openstack4j.model.network.Subnet;
63import org.slf4j.Logger;
64import org.slf4j.LoggerFactory;
65
66import java.util.Objects;
67import java.util.Set;
68import java.util.concurrent.ExecutorService;
69import java.util.stream.Collectors;
70
71import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
72import static org.onlab.util.Tools.groupedThreads;
daniel parkee8700b2017-05-11 15:50:03 +090073import static org.onosproject.net.AnnotationKeys.PORT_MAC;
74import static org.onosproject.net.AnnotationKeys.PORT_NAME;
Hyunsun Moon44aac662017-02-18 02:07:01 +090075import static org.onosproject.openstacknetworking.api.Constants.*;
76import static org.onosproject.openstacknode.OpenstackNodeService.NodeType.COMPUTE;
77
78/**
79 * Handles OpenStack router events.
80 */
81@Component(immediate = true)
82public class OpenstackRoutingHandler {
83
84 private final Logger log = LoggerFactory.getLogger(getClass());
85
86 private static final String MSG_ENABLED = "Enabled ";
87 private static final String MSG_DISABLED = "Disabled ";
88 private static final String ERR_SET_FLOWS = "Failed to set flows for router %s:";
daniel parkee8700b2017-05-11 15:50:03 +090089 private static final String ERR_UNSUPPORTED_NET_TYPE = "Unsupported network type";
Hyunsun Moon44aac662017-02-18 02:07:01 +090090
91 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
92 protected CoreService coreService;
93
94 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
95 protected LeadershipService leadershipService;
96
97 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
98 protected ClusterService clusterService;
99
100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
101 protected FlowObjectiveService flowObjectiveService;
102
103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
104 protected OpenstackNodeService osNodeService;
105
106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900107 protected OpenstackNetworkService osNetworkService;
108
109 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
110 protected OpenstackRouterService osRouterService;
111
daniel parkee8700b2017-05-11 15:50:03 +0900112 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
113 protected DeviceService deviceService;
114
Hyunsun Moon44aac662017-02-18 02:07:01 +0900115 private final ExecutorService eventExecutor = newSingleThreadScheduledExecutor(
116 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
117 private final OpenstackNodeListener osNodeListener = new InternalNodeEventListener();
118 private final OpenstackRouterListener osRouterListener = new InternalRouterEventListener();
119
120 private ApplicationId appId;
121 private NodeId localNodeId;
122
123 @Activate
124 protected void activate() {
125 appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
126 localNodeId = clusterService.getLocalNode().id();
127 leadershipService.runForLeadership(appId.name());
128 osNodeService.addListener(osNodeListener);
129 osRouterService.addListener(osRouterListener);
130
131 log.info("Started");
132 }
133
134 @Deactivate
135 protected void deactivate() {
136 osRouterService.removeListener(osRouterListener);
137 osNodeService.removeListener(osNodeListener);
138 leadershipService.withdraw(appId.name());
139 eventExecutor.shutdown();
140
141 log.info("Stopped");
142 }
143
144 private void routerUpdated(Router osRouter) {
145 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
146 if (exGateway == null) {
147 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
148 setSourceNat(iface, false);
149 });
150 } else {
151 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
152 setSourceNat(iface, exGateway.isEnableSnat());
153 });
154 }
155 }
156
157 private void routerIfaceAdded(Router osRouter, RouterInterface osRouterIface) {
158 Subnet osSubnet = osNetworkService.subnet(osRouterIface.getSubnetId());
159 if (osSubnet == null) {
160 final String error = String.format(
161 ERR_SET_FLOWS + "subnet %s does not exist",
162 osRouterIface.getId(),
163 osRouterIface.getSubnetId());
164 throw new IllegalStateException(error);
165 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900166 setInternalRoutes(osRouter, osSubnet, true);
167 setGatewayIcmp(osSubnet, true);
168 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
169 if (exGateway != null && exGateway.isEnableSnat()) {
170 setSourceNat(osRouterIface, true);
171 }
172
173 log.info("Connected subnet({}) to {}", osSubnet.getCidr(), osRouter.getName());
174 }
175
176 private void routerIfaceRemoved(Router osRouter, RouterInterface osRouterIface) {
177 Subnet osSubnet = osNetworkService.subnet(osRouterIface.getSubnetId());
178 if (osSubnet == null) {
179 final String error = String.format(
180 ERR_SET_FLOWS + "subnet %s does not exist",
181 osRouterIface.getId(),
182 osRouterIface.getSubnetId());
183 throw new IllegalStateException(error);
184 }
185
186 setInternalRoutes(osRouter, osSubnet, false);
187 setGatewayIcmp(osSubnet, false);
188 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
189 if (exGateway != null && exGateway.isEnableSnat()) {
190 setSourceNat(osRouterIface, false);
191 }
192
193 log.info("Disconnected subnet({}) from {}", osSubnet.getCidr(), osRouter.getName());
194 }
195
196 private void setSourceNat(RouterInterface routerIface, boolean install) {
197 Subnet osSubnet = osNetworkService.subnet(routerIface.getSubnetId());
198 Network osNet = osNetworkService.network(osSubnet.getNetworkId());
199
200 osNodeService.completeNodes().stream()
201 .filter(osNode -> osNode.type() == COMPUTE)
202 .forEach(osNode -> {
daniel parkee8700b2017-05-11 15:50:03 +0900203 setRulesToGateway(osNode.intBridge(), osNet.getProviderSegID(),
204 IpPrefix.valueOf(osSubnet.getCidr()), osNet.getNetworkType(),
205 install);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900206 });
207
208 // take the first outgoing packet to controller for source NAT
daniel parke49eb382017-04-05 16:48:28 +0900209 osNodeService.gatewayDeviceIds()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900210 .forEach(gwDeviceId -> setRulesToController(
211 gwDeviceId,
daniel parkee8700b2017-05-11 15:50:03 +0900212 osNet.getProviderSegID(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900213 IpPrefix.valueOf(osSubnet.getCidr()),
daniel parkee8700b2017-05-11 15:50:03 +0900214 osNet.getNetworkType(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900215 install));
216
217 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
218 log.info(updateStr + "external access for subnet({})", osSubnet.getCidr());
219 }
220
221 private void setGatewayIcmp(Subnet osSubnet, boolean install) {
222 if (Strings.isNullOrEmpty(osSubnet.getGateway())) {
223 // do nothing if no gateway is set
224 return;
225 }
226
227 // take ICMP request to a subnet gateway through gateway node group
228 Network network = osNetworkService.network(osSubnet.getNetworkId());
daniel parkee8700b2017-05-11 15:50:03 +0900229 switch (network.getNetworkType()) {
230 case VXLAN:
231 osNodeService.completeNodes().stream()
232 .filter(osNode -> osNode.type() == COMPUTE)
233 .filter(osNode -> osNode.dataIp().isPresent())
234 .forEach(osNode -> setRulesToGatewayWithDstIp(
235 osNode.intBridge(),
236 osNodeService.gatewayGroupId(osNode.intBridge(), NetworkMode.VXLAN),
237 network.getProviderSegID(),
238 IpAddress.valueOf(osSubnet.getGateway()),
239 NetworkMode.VXLAN,
240 install));
241 break;
242 case VLAN:
243 osNodeService.completeNodes().stream()
244 .filter(osNode -> osNode.type() == COMPUTE)
245 .filter(osNode -> osNode.vlanPort().isPresent())
246 .forEach(osNode -> setRulesToGatewayWithDstIp(
247 osNode.intBridge(),
248 osNodeService.gatewayGroupId(osNode.intBridge(), NetworkMode.VLAN),
249 network.getProviderSegID(),
250 IpAddress.valueOf(osSubnet.getGateway()),
251 NetworkMode.VLAN,
252 install));
253 break;
254 default:
255 final String error = String.format(
256 ERR_UNSUPPORTED_NET_TYPE + "%s",
257 network.getNetworkType().toString());
258 throw new IllegalStateException(error);
259 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900260
261 IpAddress gatewayIp = IpAddress.valueOf(osSubnet.getGateway());
daniel parke49eb382017-04-05 16:48:28 +0900262 osNodeService.gatewayDeviceIds()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900263 .forEach(gwDeviceId -> setGatewayIcmpRule(
264 gatewayIp,
265 gwDeviceId,
266 install
267 ));
268
269 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
270 log.debug(updateStr + "ICMP to {}", osSubnet.getGateway());
271 }
272
273 private void setInternalRoutes(Router osRouter, Subnet updatedSubnet, boolean install) {
daniel parkee8700b2017-05-11 15:50:03 +0900274 Network updatedNetwork = osNetworkService.network(updatedSubnet.getNetworkId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900275 Set<Subnet> routableSubnets = routableSubnets(osRouter, updatedSubnet.getId());
daniel parkee8700b2017-05-11 15:50:03 +0900276 String updatedSegmendId = getSegmentId(updatedSubnet);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900277
278 // installs rule from/to my subnet intentionally to fix ICMP failure
279 // to my subnet gateway if no external gateway added to the router
280 osNodeService.completeNodes().stream()
281 .filter(osNode -> osNode.type() == COMPUTE)
282 .forEach(osNode -> {
283 setInternalRouterRules(
284 osNode.intBridge(),
daniel parkee8700b2017-05-11 15:50:03 +0900285 updatedSegmendId,
286 updatedSegmendId,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900287 IpPrefix.valueOf(updatedSubnet.getCidr()),
288 IpPrefix.valueOf(updatedSubnet.getCidr()),
daniel parkee8700b2017-05-11 15:50:03 +0900289 updatedNetwork.getNetworkType(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900290 install
291 );
292
293 routableSubnets.forEach(subnet -> {
294 setInternalRouterRules(
295 osNode.intBridge(),
daniel parkee8700b2017-05-11 15:50:03 +0900296 updatedSegmendId,
297 getSegmentId(subnet),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900298 IpPrefix.valueOf(updatedSubnet.getCidr()),
299 IpPrefix.valueOf(subnet.getCidr()),
daniel parkee8700b2017-05-11 15:50:03 +0900300 updatedNetwork.getNetworkType(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900301 install
302 );
303 setInternalRouterRules(
304 osNode.intBridge(),
daniel parkee8700b2017-05-11 15:50:03 +0900305 getSegmentId(subnet),
306 updatedSegmendId,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900307 IpPrefix.valueOf(subnet.getCidr()),
308 IpPrefix.valueOf(updatedSubnet.getCidr()),
daniel parkee8700b2017-05-11 15:50:03 +0900309 updatedNetwork.getNetworkType(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900310 install
311 );
312 });
313 });
314
daniel parkee8700b2017-05-11 15:50:03 +0900315
Hyunsun Moon44aac662017-02-18 02:07:01 +0900316 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
317 routableSubnets.forEach(subnet -> log.debug(
318 updateStr + "route between subnet:{} and subnet:{}",
319 subnet.getCidr(),
320 updatedSubnet.getCidr()));
321 }
322
323 private Set<Subnet> routableSubnets(Router osRouter, String osSubnetId) {
324 Set<Subnet> osSubnets = osRouterService.routerInterfaces(osRouter.getId())
325 .stream()
326 .filter(iface -> !Objects.equals(iface.getSubnetId(), osSubnetId))
327 .map(iface -> osNetworkService.subnet(iface.getSubnetId()))
328 .collect(Collectors.toSet());
329 return ImmutableSet.copyOf(osSubnets);
330 }
331
daniel parkee8700b2017-05-11 15:50:03 +0900332 private String getSegmentId(Subnet osSubnet) {
333 return osNetworkService.network(osSubnet.getNetworkId()).getProviderSegID();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900334 }
335
336 private void setGatewayIcmpRule(IpAddress gatewayIp, DeviceId deviceId, boolean install) {
337 TrafficSelector selector = DefaultTrafficSelector.builder()
338 .matchEthType(Ethernet.TYPE_IPV4)
339 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
340 .matchIPDst(gatewayIp.toIpPrefix())
341 .build();
342
343 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
344 .setOutput(PortNumber.CONTROLLER)
345 .build();
346
347 RulePopulatorUtil.setRule(
348 flowObjectiveService,
349 appId,
350 deviceId,
351 selector,
352 treatment,
353 ForwardingObjective.Flag.VERSATILE,
354 PRIORITY_ICMP_RULE,
355 install);
356 }
357
daniel parkee8700b2017-05-11 15:50:03 +0900358 private void setInternalRouterRules(DeviceId deviceId, String srcSegmentId, String dstSegmentId,
359 IpPrefix srcSubnet, IpPrefix dstSubnet,
360 NetworkType networkType, boolean install) {
361 TrafficSelector selector;
362 TrafficTreatment treatment;
363 switch (networkType) {
364 case VXLAN:
365 selector = DefaultTrafficSelector.builder()
366 .matchEthType(Ethernet.TYPE_IPV4)
367 .matchTunnelId(Long.parseLong(srcSegmentId))
368 .matchIPSrc(srcSubnet)
369 .matchIPDst(dstSubnet)
370 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900371
daniel parkee8700b2017-05-11 15:50:03 +0900372 treatment = DefaultTrafficTreatment.builder()
373 .setTunnelId(Long.parseLong(dstSegmentId))
374 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900375
daniel parkee8700b2017-05-11 15:50:03 +0900376 RulePopulatorUtil.setRule(
377 flowObjectiveService,
378 appId,
379 deviceId,
380 selector,
381 treatment,
382 ForwardingObjective.Flag.SPECIFIC,
383 PRIORITY_INTERNAL_ROUTING_RULE,
384 install);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900385
daniel parkee8700b2017-05-11 15:50:03 +0900386 selector = DefaultTrafficSelector.builder()
387 .matchEthType(Ethernet.TYPE_IPV4)
388 .matchTunnelId(Long.parseLong(dstSegmentId))
389 .matchIPSrc(srcSubnet)
390 .matchIPDst(dstSubnet)
391 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900392
daniel parkee8700b2017-05-11 15:50:03 +0900393 treatment = DefaultTrafficTreatment.builder()
394 .setTunnelId(Long.parseLong(dstSegmentId))
395 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900396
daniel parkee8700b2017-05-11 15:50:03 +0900397 RulePopulatorUtil.setRule(
398 flowObjectiveService,
399 appId,
400 deviceId,
401 selector,
402 treatment,
403 ForwardingObjective.Flag.SPECIFIC,
404 PRIORITY_INTERNAL_ROUTING_RULE,
405 install);
406 break;
407 case VLAN:
408 selector = DefaultTrafficSelector.builder()
409 .matchEthType(Ethernet.TYPE_IPV4)
410 .matchVlanId(VlanId.vlanId(srcSegmentId))
411 .matchIPSrc(srcSubnet)
412 .matchIPDst(dstSubnet)
413 .build();
414
415 treatment = DefaultTrafficTreatment.builder()
416 .setVlanId(VlanId.vlanId(dstSegmentId))
417 .build();
418
419 RulePopulatorUtil.setRule(
420 flowObjectiveService,
421 appId,
422 deviceId,
423 selector,
424 treatment,
425 ForwardingObjective.Flag.SPECIFIC,
426 PRIORITY_INTERNAL_ROUTING_RULE,
427 install);
428
429 selector = DefaultTrafficSelector.builder()
430 .matchEthType(Ethernet.TYPE_IPV4)
431 .matchVlanId(VlanId.vlanId(dstSegmentId))
432 .matchIPSrc(srcSubnet)
433 .matchIPDst(dstSubnet)
434 .build();
435
436 treatment = DefaultTrafficTreatment.builder()
437 .setVlanId(VlanId.vlanId(dstSegmentId))
438 .build();
439
440 RulePopulatorUtil.setRule(
441 flowObjectiveService,
442 appId,
443 deviceId,
444 selector,
445 treatment,
446 ForwardingObjective.Flag.SPECIFIC,
447 PRIORITY_INTERNAL_ROUTING_RULE,
448 install);
449 break;
450 default:
451 final String error = String.format(
452 ERR_UNSUPPORTED_NET_TYPE + "%s",
453 networkType.toString());
454 throw new IllegalStateException(error);
455 }
456
Hyunsun Moon44aac662017-02-18 02:07:01 +0900457 }
458
daniel parkee8700b2017-05-11 15:50:03 +0900459 private void setRulesToGateway(DeviceId deviceId, String segmentId, IpPrefix srcSubnet,
460 NetworkType networkType, boolean install) {
461 TrafficTreatment treatment;
462 GroupId groupId;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900463
daniel parkee8700b2017-05-11 15:50:03 +0900464 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
465 .matchEthType(Ethernet.TYPE_IPV4)
466 .matchIPSrc(srcSubnet)
467 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
468
469 switch (networkType) {
470 case VXLAN:
471 sBuilder.matchTunnelId(Long.parseLong(segmentId));
472
473 groupId = osNodeService.gatewayGroupId(deviceId, NetworkMode.VXLAN);
474 break;
475 case VLAN:
476 sBuilder.matchVlanId(VlanId.vlanId(segmentId));
477
478 groupId = osNodeService.gatewayGroupId(deviceId, NetworkMode.VLAN);
479 break;
480 default:
481 final String error = String.format(
482 ERR_UNSUPPORTED_NET_TYPE + "%s",
483 networkType.toString());
484 throw new IllegalStateException(error);
485 }
486
487 treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900488 .group(groupId)
489 .build();
490
491 RulePopulatorUtil.setRule(
492 flowObjectiveService,
493 appId,
494 deviceId,
daniel parkee8700b2017-05-11 15:50:03 +0900495 sBuilder.build(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900496 treatment,
497 ForwardingObjective.Flag.SPECIFIC,
498 PRIORITY_EXTERNAL_ROUTING_RULE,
499 install);
500 }
501
daniel parkee8700b2017-05-11 15:50:03 +0900502 private void setRulesToController(DeviceId deviceId, String segmentId, IpPrefix srcSubnet,
503 NetworkType networkType, boolean install) {
504 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900505 .matchEthType(Ethernet.TYPE_IPV4)
daniel parkee8700b2017-05-11 15:50:03 +0900506 .matchIPSrc(srcSubnet);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900507
daniel parkee8700b2017-05-11 15:50:03 +0900508 switch (networkType) {
509 case VXLAN:
510 sBuilder.matchTunnelId(Long.parseLong(segmentId))
511 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
512 break;
513 case VLAN:
514 sBuilder.matchVlanId(VlanId.vlanId(segmentId))
515 .matchEthDst(MacAddress.valueOf(vlanPortMac(deviceId)));
516 break;
517 default:
518 final String error = String.format(
519 ERR_UNSUPPORTED_NET_TYPE + "%s",
520 networkType.toString());
521 throw new IllegalStateException(error);
522 }
523
524 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
525 .setEthDst(Constants.DEFAULT_GATEWAY_MAC);
526
527 if (networkType.equals(NetworkType.VLAN)) {
528 tBuilder.popVlan();
529 }
530
531 tBuilder.setOutput(PortNumber.CONTROLLER);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900532
533 RulePopulatorUtil.setRule(
534 flowObjectiveService,
535 appId,
536 deviceId,
daniel parkee8700b2017-05-11 15:50:03 +0900537 sBuilder.build(),
538 tBuilder.build(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900539 ForwardingObjective.Flag.VERSATILE,
540 PRIORITY_EXTERNAL_ROUTING_RULE,
541 install);
542 }
543
daniel parkee8700b2017-05-11 15:50:03 +0900544 private String vlanPortMac(DeviceId deviceId) {
545 return deviceService.getPorts(deviceId).stream()
546 .filter(p -> p.annotations()
547 .value(PORT_NAME).equals(osNodeService.gatewayNode(deviceId).vlanPort().get()) && p.isEnabled())
548 .findFirst().get().annotations().value(PORT_MAC);
549 }
550
551 private void setRulesToGatewayWithDstIp(DeviceId deviceId, GroupId groupId, String segmentId,
552 IpAddress dstIp, NetworkMode networkMode, boolean install) {
553 TrafficSelector selector;
554 if (networkMode.equals(NetworkMode.VXLAN)) {
555 selector = DefaultTrafficSelector.builder()
556 .matchEthType(Ethernet.TYPE_IPV4)
557 .matchTunnelId(Long.valueOf(segmentId))
558 .matchIPDst(dstIp.toIpPrefix())
559 .build();
560 } else {
561 selector = DefaultTrafficSelector.builder()
562 .matchEthType(Ethernet.TYPE_IPV4)
563 .matchVlanId(VlanId.vlanId(segmentId))
564 .matchIPDst(dstIp.toIpPrefix())
565 .build();
566 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900567
568 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
569 .group(groupId)
570 .build();
571
572 RulePopulatorUtil.setRule(
573 flowObjectiveService,
574 appId,
575 deviceId,
576 selector,
577 treatment,
578 ForwardingObjective.Flag.SPECIFIC,
579 PRIORITY_SWITCHING_RULE,
580 install);
581 }
582
583 private class InternalRouterEventListener implements OpenstackRouterListener {
584
585 @Override
586 public boolean isRelevant(OpenstackRouterEvent event) {
587 // do not allow to proceed without leadership
588 NodeId leader = leadershipService.getLeader(appId.name());
589 return Objects.equals(localNodeId, leader);
590 }
591
592 // FIXME only one leader in the cluster should process
593 @Override
594 public void event(OpenstackRouterEvent event) {
595 switch (event.type()) {
596 case OPENSTACK_ROUTER_CREATED:
597 log.debug("Router(name:{}, ID:{}) is created",
598 event.subject().getName(),
599 event.subject().getId());
600 eventExecutor.execute(() -> routerUpdated(event.subject()));
601 break;
602 case OPENSTACK_ROUTER_UPDATED:
603 log.debug("Router(name:{}, ID:{}) is updated",
604 event.subject().getName(),
605 event.subject().getId());
606 eventExecutor.execute(() -> routerUpdated(event.subject()));
607 break;
608 case OPENSTACK_ROUTER_REMOVED:
609 log.debug("Router(name:{}, ID:{}) is removed",
610 event.subject().getName(),
611 event.subject().getId());
612 break;
613 case OPENSTACK_ROUTER_INTERFACE_ADDED:
614 log.debug("Router interface {} added to router {}",
615 event.routerIface().getPortId(),
616 event.routerIface().getId());
617 eventExecutor.execute(() -> routerIfaceAdded(
618 event.subject(),
619 event.routerIface()));
620 break;
621 case OPENSTACK_ROUTER_INTERFACE_UPDATED:
622 log.debug("Router interface {} on {} updated",
623 event.routerIface().getPortId(),
624 event.routerIface().getId());
625 break;
626 case OPENSTACK_ROUTER_INTERFACE_REMOVED:
627 log.debug("Router interface {} removed from router {}",
628 event.routerIface().getPortId(),
629 event.routerIface().getId());
630 eventExecutor.execute(() -> routerIfaceRemoved(
631 event.subject(),
632 event.routerIface()));
633 break;
634 case OPENSTACK_ROUTER_GATEWAY_ADDED:
635 case OPENSTACK_ROUTER_GATEWAY_REMOVED:
636 case OPENSTACK_FLOATING_IP_CREATED:
637 case OPENSTACK_FLOATING_IP_UPDATED:
638 case OPENSTACK_FLOATING_IP_REMOVED:
639 case OPENSTACK_FLOATING_IP_ASSOCIATED:
640 case OPENSTACK_FLOATING_IP_DISASSOCIATED:
641 default:
642 // do nothing for the other events
643 break;
644 }
645 }
646 }
647
648 private class InternalNodeEventListener implements OpenstackNodeListener {
649
650 @Override
651 public boolean isRelevant(OpenstackNodeEvent event) {
652 // do not allow to proceed without leadership
653 NodeId leader = leadershipService.getLeader(appId.name());
654 return Objects.equals(localNodeId, leader);
655 }
656
657 @Override
658 public void event(OpenstackNodeEvent event) {
659 OpenstackNode osNode = event.subject();
660
661 switch (event.type()) {
662 case COMPLETE:
663 case INCOMPLETE:
664 eventExecutor.execute(() -> {
Hyunsun Moon0e058f22017-04-19 17:00:52 +0900665 log.info("Reconfigure routers for {}", osNode.hostname());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900666 reconfigureRouters();
667 });
668 break;
669 case INIT:
670 case DEVICE_CREATED:
671 default:
672 break;
673 }
674 }
675
676 private void reconfigureRouters() {
677 osRouterService.routers().forEach(osRouter -> {
678 routerUpdated(osRouter);
679 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
680 routerIfaceAdded(osRouter, iface);
681 });
682 });
683 }
684 }
685}