blob: 084f1b82d4c8f2d4159efd549308895f50c613b0 [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.VlanId;
Hyunsun Moon44aac662017-02-18 02:07:01 +090030import org.onosproject.cluster.ClusterService;
31import org.onosproject.cluster.LeadershipService;
32import org.onosproject.cluster.NodeId;
33import org.onosproject.core.ApplicationId;
34import org.onosproject.core.CoreService;
35import org.onosproject.core.GroupId;
36import org.onosproject.net.DeviceId;
37import org.onosproject.net.PortNumber;
38import org.onosproject.net.flow.DefaultTrafficSelector;
39import org.onosproject.net.flow.DefaultTrafficTreatment;
40import org.onosproject.net.flow.TrafficSelector;
41import org.onosproject.net.flow.TrafficTreatment;
Hyunsun Moon44aac662017-02-18 02:07:01 +090042import org.onosproject.openstacknetworking.api.Constants;
sanghodc375372017-06-08 10:41:30 +090043import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090044import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
45import org.onosproject.openstacknetworking.api.OpenstackRouterEvent;
46import org.onosproject.openstacknetworking.api.OpenstackRouterListener;
47import org.onosproject.openstacknetworking.api.OpenstackRouterService;
Hyunsun Moon0d457362017-06-27 17:19:41 +090048import org.onosproject.openstacknode.api.OpenstackNode;
49import org.onosproject.openstacknode.api.OpenstackNode.NetworkMode;
50import org.onosproject.openstacknode.api.OpenstackNodeEvent;
51import org.onosproject.openstacknode.api.OpenstackNodeListener;
52import org.onosproject.openstacknode.api.OpenstackNodeService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090053import org.openstack4j.model.network.ExternalGateway;
54import org.openstack4j.model.network.Network;
daniel parkee8700b2017-05-11 15:50:03 +090055import org.openstack4j.model.network.NetworkType;
Hyunsun Moon44aac662017-02-18 02:07:01 +090056import org.openstack4j.model.network.Router;
57import org.openstack4j.model.network.RouterInterface;
58import org.openstack4j.model.network.Subnet;
59import org.slf4j.Logger;
60import org.slf4j.LoggerFactory;
61
62import java.util.Objects;
63import java.util.Set;
64import java.util.concurrent.ExecutorService;
65import java.util.stream.Collectors;
66
67import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
68import static org.onlab.util.Tools.groupedThreads;
Hyunsun Moon0d457362017-06-27 17:19:41 +090069import static org.onosproject.openstacknetworking.api.Constants.*;
70import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
71import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
Hyunsun Moon44aac662017-02-18 02:07:01 +090072
73/**
74 * Handles OpenStack router events.
75 */
76@Component(immediate = true)
77public class OpenstackRoutingHandler {
78
79 private final Logger log = LoggerFactory.getLogger(getClass());
80
81 private static final String MSG_ENABLED = "Enabled ";
82 private static final String MSG_DISABLED = "Disabled ";
83 private static final String ERR_SET_FLOWS = "Failed to set flows for router %s:";
daniel parkee8700b2017-05-11 15:50:03 +090084 private static final String ERR_UNSUPPORTED_NET_TYPE = "Unsupported network type";
Hyunsun Moon44aac662017-02-18 02:07:01 +090085
86 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
87 protected CoreService coreService;
88
89 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
90 protected LeadershipService leadershipService;
91
92 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
93 protected ClusterService clusterService;
94
95 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon44aac662017-02-18 02:07:01 +090096 protected OpenstackNodeService osNodeService;
97
98 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon44aac662017-02-18 02:07:01 +090099 protected OpenstackNetworkService osNetworkService;
100
101 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
102 protected OpenstackRouterService osRouterService;
103
daniel parkee8700b2017-05-11 15:50:03 +0900104 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sanghodc375372017-06-08 10:41:30 +0900105 protected OpenstackFlowRuleService osFlowRuleService;
106
Hyunsun Moon44aac662017-02-18 02:07:01 +0900107 private final ExecutorService eventExecutor = newSingleThreadScheduledExecutor(
108 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
109 private final OpenstackNodeListener osNodeListener = new InternalNodeEventListener();
110 private final OpenstackRouterListener osRouterListener = new InternalRouterEventListener();
111
112 private ApplicationId appId;
113 private NodeId localNodeId;
114
115 @Activate
116 protected void activate() {
117 appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
118 localNodeId = clusterService.getLocalNode().id();
119 leadershipService.runForLeadership(appId.name());
120 osNodeService.addListener(osNodeListener);
121 osRouterService.addListener(osRouterListener);
122
123 log.info("Started");
124 }
125
126 @Deactivate
127 protected void deactivate() {
128 osRouterService.removeListener(osRouterListener);
129 osNodeService.removeListener(osNodeListener);
130 leadershipService.withdraw(appId.name());
131 eventExecutor.shutdown();
132
133 log.info("Stopped");
134 }
135
136 private void routerUpdated(Router osRouter) {
137 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
138 if (exGateway == null) {
139 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
140 setSourceNat(iface, false);
141 });
142 } else {
143 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
144 setSourceNat(iface, exGateway.isEnableSnat());
145 });
146 }
147 }
148
149 private void routerIfaceAdded(Router osRouter, RouterInterface osRouterIface) {
150 Subnet osSubnet = osNetworkService.subnet(osRouterIface.getSubnetId());
151 if (osSubnet == null) {
152 final String error = String.format(
153 ERR_SET_FLOWS + "subnet %s does not exist",
154 osRouterIface.getId(),
155 osRouterIface.getSubnetId());
156 throw new IllegalStateException(error);
157 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900158 setInternalRoutes(osRouter, osSubnet, true);
159 setGatewayIcmp(osSubnet, true);
160 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
161 if (exGateway != null && exGateway.isEnableSnat()) {
162 setSourceNat(osRouterIface, true);
163 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900164 log.info("Connected subnet({}) to {}", osSubnet.getCidr(), osRouter.getName());
165 }
166
167 private void routerIfaceRemoved(Router osRouter, RouterInterface osRouterIface) {
168 Subnet osSubnet = osNetworkService.subnet(osRouterIface.getSubnetId());
169 if (osSubnet == null) {
170 final String error = String.format(
171 ERR_SET_FLOWS + "subnet %s does not exist",
172 osRouterIface.getId(),
173 osRouterIface.getSubnetId());
174 throw new IllegalStateException(error);
175 }
176
177 setInternalRoutes(osRouter, osSubnet, false);
178 setGatewayIcmp(osSubnet, false);
179 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
180 if (exGateway != null && exGateway.isEnableSnat()) {
181 setSourceNat(osRouterIface, false);
182 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900183 log.info("Disconnected subnet({}) from {}", osSubnet.getCidr(), osRouter.getName());
184 }
185
186 private void setSourceNat(RouterInterface routerIface, boolean install) {
187 Subnet osSubnet = osNetworkService.subnet(routerIface.getSubnetId());
188 Network osNet = osNetworkService.network(osSubnet.getNetworkId());
189
Hyunsun Moon0d457362017-06-27 17:19:41 +0900190 osNodeService.completeNodes(COMPUTE).forEach(cNode -> {
191 setRulesToGateway(cNode, osNet.getProviderSegID(),
192 IpPrefix.valueOf(osSubnet.getCidr()), osNet.getNetworkType(),
193 install);
194 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900195
196 // take the first outgoing packet to controller for source NAT
Hyunsun Moon0d457362017-06-27 17:19:41 +0900197 osNodeService.completeNodes(GATEWAY).forEach(gNode -> {
198 setRulesToController(
199 gNode,
200 osNet.getProviderSegID(),
201 IpPrefix.valueOf(osSubnet.getCidr()),
202 osNet.getNetworkType(),
203 install);
204 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900205
206 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
207 log.info(updateStr + "external access for subnet({})", osSubnet.getCidr());
208 }
209
210 private void setGatewayIcmp(Subnet osSubnet, boolean install) {
211 if (Strings.isNullOrEmpty(osSubnet.getGateway())) {
212 // do nothing if no gateway is set
213 return;
214 }
215
216 // take ICMP request to a subnet gateway through gateway node group
217 Network network = osNetworkService.network(osSubnet.getNetworkId());
daniel parkee8700b2017-05-11 15:50:03 +0900218 switch (network.getNetworkType()) {
219 case VXLAN:
Hyunsun Moon0d457362017-06-27 17:19:41 +0900220 osNodeService.completeNodes(COMPUTE).stream()
221 .filter(cNode -> cNode.dataIp() != null)
222 .forEach(cNode -> setRulesToGatewayWithDstIp(
223 cNode,
224 cNode.gatewayGroupId(NetworkMode.VXLAN),
daniel parkee8700b2017-05-11 15:50:03 +0900225 network.getProviderSegID(),
226 IpAddress.valueOf(osSubnet.getGateway()),
227 NetworkMode.VXLAN,
228 install));
229 break;
230 case VLAN:
Hyunsun Moon0d457362017-06-27 17:19:41 +0900231 osNodeService.completeNodes(COMPUTE).stream()
232 .filter(cNode -> cNode.vlanPortNum() != null)
233 .forEach(cNode -> setRulesToGatewayWithDstIp(
234 cNode,
235 cNode.gatewayGroupId(NetworkMode.VLAN),
daniel parkee8700b2017-05-11 15:50:03 +0900236 network.getProviderSegID(),
237 IpAddress.valueOf(osSubnet.getGateway()),
238 NetworkMode.VLAN,
239 install));
240 break;
241 default:
242 final String error = String.format(
243 ERR_UNSUPPORTED_NET_TYPE + "%s",
244 network.getNetworkType().toString());
245 throw new IllegalStateException(error);
246 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900247
248 IpAddress gatewayIp = IpAddress.valueOf(osSubnet.getGateway());
Hyunsun Moon0d457362017-06-27 17:19:41 +0900249 osNodeService.completeNodes(GATEWAY).forEach(gNode -> {
250 setGatewayIcmpRule(
251 gatewayIp,
252 gNode.intgBridge(),
253 install
254 );
255 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900256
257 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
258 log.debug(updateStr + "ICMP to {}", osSubnet.getGateway());
259 }
260
261 private void setInternalRoutes(Router osRouter, Subnet updatedSubnet, boolean install) {
daniel parkee8700b2017-05-11 15:50:03 +0900262 Network updatedNetwork = osNetworkService.network(updatedSubnet.getNetworkId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900263 Set<Subnet> routableSubnets = routableSubnets(osRouter, updatedSubnet.getId());
daniel parkee8700b2017-05-11 15:50:03 +0900264 String updatedSegmendId = getSegmentId(updatedSubnet);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900265
266 // installs rule from/to my subnet intentionally to fix ICMP failure
267 // to my subnet gateway if no external gateway added to the router
Hyunsun Moon0d457362017-06-27 17:19:41 +0900268 osNodeService.completeNodes(COMPUTE).forEach(cNode -> {
269 setInternalRouterRules(
270 cNode.intgBridge(),
271 updatedSegmendId,
272 updatedSegmendId,
273 IpPrefix.valueOf(updatedSubnet.getCidr()),
274 IpPrefix.valueOf(updatedSubnet.getCidr()),
275 updatedNetwork.getNetworkType(),
276 install
277 );
Hyunsun Moon44aac662017-02-18 02:07:01 +0900278
Hyunsun Moon0d457362017-06-27 17:19:41 +0900279 routableSubnets.forEach(subnet -> {
280 setInternalRouterRules(
281 cNode.intgBridge(),
282 updatedSegmendId,
283 getSegmentId(subnet),
284 IpPrefix.valueOf(updatedSubnet.getCidr()),
285 IpPrefix.valueOf(subnet.getCidr()),
286 updatedNetwork.getNetworkType(),
287 install
288 );
289 setInternalRouterRules(
290 cNode.intgBridge(),
291 getSegmentId(subnet),
292 updatedSegmendId,
293 IpPrefix.valueOf(subnet.getCidr()),
294 IpPrefix.valueOf(updatedSubnet.getCidr()),
295 updatedNetwork.getNetworkType(),
296 install
297 );
298 });
299 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900300
daniel parkee8700b2017-05-11 15:50:03 +0900301
Hyunsun Moon44aac662017-02-18 02:07:01 +0900302 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
303 routableSubnets.forEach(subnet -> log.debug(
304 updateStr + "route between subnet:{} and subnet:{}",
305 subnet.getCidr(),
306 updatedSubnet.getCidr()));
307 }
308
309 private Set<Subnet> routableSubnets(Router osRouter, String osSubnetId) {
310 Set<Subnet> osSubnets = osRouterService.routerInterfaces(osRouter.getId())
311 .stream()
312 .filter(iface -> !Objects.equals(iface.getSubnetId(), osSubnetId))
313 .map(iface -> osNetworkService.subnet(iface.getSubnetId()))
314 .collect(Collectors.toSet());
315 return ImmutableSet.copyOf(osSubnets);
316 }
317
daniel parkee8700b2017-05-11 15:50:03 +0900318 private String getSegmentId(Subnet osSubnet) {
319 return osNetworkService.network(osSubnet.getNetworkId()).getProviderSegID();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900320 }
321
322 private void setGatewayIcmpRule(IpAddress gatewayIp, DeviceId deviceId, boolean install) {
323 TrafficSelector selector = DefaultTrafficSelector.builder()
324 .matchEthType(Ethernet.TYPE_IPV4)
325 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900326 .matchIPDst(gatewayIp.getIp4Address().toIpPrefix())
Hyunsun Moon44aac662017-02-18 02:07:01 +0900327 .build();
328
329 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
330 .setOutput(PortNumber.CONTROLLER)
331 .build();
332
sanghodc375372017-06-08 10:41:30 +0900333 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900334 appId,
335 deviceId,
336 selector,
337 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900338 PRIORITY_ICMP_RULE,
sanghodc375372017-06-08 10:41:30 +0900339 Constants.GW_COMMON_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900340 install);
341 }
342
daniel parkee8700b2017-05-11 15:50:03 +0900343 private void setInternalRouterRules(DeviceId deviceId, String srcSegmentId, String dstSegmentId,
344 IpPrefix srcSubnet, IpPrefix dstSubnet,
345 NetworkType networkType, boolean install) {
346 TrafficSelector selector;
347 TrafficTreatment treatment;
348 switch (networkType) {
349 case VXLAN:
350 selector = DefaultTrafficSelector.builder()
351 .matchEthType(Ethernet.TYPE_IPV4)
352 .matchTunnelId(Long.parseLong(srcSegmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900353 .matchIPSrc(srcSubnet.getIp4Prefix())
354 .matchIPDst(dstSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900355 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900356
daniel parkee8700b2017-05-11 15:50:03 +0900357 treatment = DefaultTrafficTreatment.builder()
358 .setTunnelId(Long.parseLong(dstSegmentId))
sanghodc375372017-06-08 10:41:30 +0900359 .transition(FORWARDING_TABLE)
daniel parkee8700b2017-05-11 15:50:03 +0900360 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900361
sanghodc375372017-06-08 10:41:30 +0900362 osFlowRuleService.setRule(
daniel parkee8700b2017-05-11 15:50:03 +0900363 appId,
364 deviceId,
365 selector,
366 treatment,
daniel parkee8700b2017-05-11 15:50:03 +0900367 PRIORITY_INTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900368 ROUTING_TABLE,
daniel parkee8700b2017-05-11 15:50:03 +0900369 install);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900370
daniel parkee8700b2017-05-11 15:50:03 +0900371 selector = DefaultTrafficSelector.builder()
372 .matchEthType(Ethernet.TYPE_IPV4)
373 .matchTunnelId(Long.parseLong(dstSegmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900374 .matchIPSrc(srcSubnet.getIp4Prefix())
375 .matchIPDst(dstSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900376 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900377
daniel parkee8700b2017-05-11 15:50:03 +0900378 treatment = DefaultTrafficTreatment.builder()
379 .setTunnelId(Long.parseLong(dstSegmentId))
sanghodc375372017-06-08 10:41:30 +0900380 .transition(FORWARDING_TABLE)
daniel parkee8700b2017-05-11 15:50:03 +0900381 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900382
sanghodc375372017-06-08 10:41:30 +0900383 osFlowRuleService.setRule(
daniel parkee8700b2017-05-11 15:50:03 +0900384 appId,
385 deviceId,
386 selector,
387 treatment,
daniel parkee8700b2017-05-11 15:50:03 +0900388 PRIORITY_INTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900389 ROUTING_TABLE,
daniel parkee8700b2017-05-11 15:50:03 +0900390 install);
391 break;
392 case VLAN:
393 selector = DefaultTrafficSelector.builder()
394 .matchEthType(Ethernet.TYPE_IPV4)
395 .matchVlanId(VlanId.vlanId(srcSegmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900396 .matchIPSrc(srcSubnet.getIp4Prefix())
397 .matchIPDst(dstSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900398 .build();
399
400 treatment = DefaultTrafficTreatment.builder()
401 .setVlanId(VlanId.vlanId(dstSegmentId))
sanghodc375372017-06-08 10:41:30 +0900402 .transition(FORWARDING_TABLE)
daniel parkee8700b2017-05-11 15:50:03 +0900403 .build();
404
sanghodc375372017-06-08 10:41:30 +0900405 osFlowRuleService.setRule(
daniel parkee8700b2017-05-11 15:50:03 +0900406 appId,
407 deviceId,
408 selector,
409 treatment,
daniel parkee8700b2017-05-11 15:50:03 +0900410 PRIORITY_INTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900411 ROUTING_TABLE,
daniel parkee8700b2017-05-11 15:50:03 +0900412 install);
413
414 selector = DefaultTrafficSelector.builder()
415 .matchEthType(Ethernet.TYPE_IPV4)
416 .matchVlanId(VlanId.vlanId(dstSegmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900417 .matchIPSrc(srcSubnet.getIp4Prefix())
418 .matchIPDst(dstSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900419 .build();
420
421 treatment = DefaultTrafficTreatment.builder()
422 .setVlanId(VlanId.vlanId(dstSegmentId))
sanghodc375372017-06-08 10:41:30 +0900423 .transition(FORWARDING_TABLE)
daniel parkee8700b2017-05-11 15:50:03 +0900424 .build();
425
sanghodc375372017-06-08 10:41:30 +0900426 osFlowRuleService.setRule(
daniel parkee8700b2017-05-11 15:50:03 +0900427 appId,
428 deviceId,
429 selector,
430 treatment,
daniel parkee8700b2017-05-11 15:50:03 +0900431 PRIORITY_INTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900432 ROUTING_TABLE,
daniel parkee8700b2017-05-11 15:50:03 +0900433 install);
434 break;
435 default:
436 final String error = String.format(
437 ERR_UNSUPPORTED_NET_TYPE + "%s",
438 networkType.toString());
439 throw new IllegalStateException(error);
440 }
441
Hyunsun Moon44aac662017-02-18 02:07:01 +0900442 }
443
Hyunsun Moon0d457362017-06-27 17:19:41 +0900444 private void setRulesToGateway(OpenstackNode osNode, String segmentId, IpPrefix srcSubnet,
daniel parkee8700b2017-05-11 15:50:03 +0900445 NetworkType networkType, boolean install) {
446 TrafficTreatment treatment;
447 GroupId groupId;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900448
daniel parkee8700b2017-05-11 15:50:03 +0900449 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
450 .matchEthType(Ethernet.TYPE_IPV4)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900451 .matchIPSrc(srcSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900452 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
453
454 switch (networkType) {
455 case VXLAN:
456 sBuilder.matchTunnelId(Long.parseLong(segmentId));
Hyunsun Moon0d457362017-06-27 17:19:41 +0900457 groupId = osNode.gatewayGroupId(NetworkMode.VXLAN);
daniel parkee8700b2017-05-11 15:50:03 +0900458 break;
459 case VLAN:
460 sBuilder.matchVlanId(VlanId.vlanId(segmentId));
Hyunsun Moon0d457362017-06-27 17:19:41 +0900461 groupId = osNode.gatewayGroupId(NetworkMode.VLAN);
daniel parkee8700b2017-05-11 15:50:03 +0900462 break;
463 default:
464 final String error = String.format(
465 ERR_UNSUPPORTED_NET_TYPE + "%s",
466 networkType.toString());
467 throw new IllegalStateException(error);
468 }
469
470 treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900471 .group(groupId)
472 .build();
473
sanghodc375372017-06-08 10:41:30 +0900474 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900475 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900476 osNode.intgBridge(),
daniel parkee8700b2017-05-11 15:50:03 +0900477 sBuilder.build(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900478 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900479 PRIORITY_EXTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900480 ROUTING_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900481 install);
482 }
483
Hyunsun Moon0d457362017-06-27 17:19:41 +0900484 private void setRulesToController(OpenstackNode osNode, String segmentId,
485 IpPrefix srcSubnet,
daniel parkee8700b2017-05-11 15:50:03 +0900486 NetworkType networkType, boolean install) {
487 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900488 .matchEthType(Ethernet.TYPE_IPV4)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900489 .matchIPSrc(srcSubnet.getIp4Prefix());
490
491 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
492 .setEthDst(Constants.DEFAULT_GATEWAY_MAC)
493 .setOutput(PortNumber.CONTROLLER);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900494
daniel parkee8700b2017-05-11 15:50:03 +0900495 switch (networkType) {
496 case VXLAN:
497 sBuilder.matchTunnelId(Long.parseLong(segmentId))
498 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
499 break;
500 case VLAN:
501 sBuilder.matchVlanId(VlanId.vlanId(segmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900502 .matchEthDst(osNode.vlanPortMac());
503 tBuilder.popVlan();
daniel parkee8700b2017-05-11 15:50:03 +0900504 break;
505 default:
Hyunsun Moon0d457362017-06-27 17:19:41 +0900506 final String error = String.format(ERR_UNSUPPORTED_NET_TYPE + "%s",
daniel parkee8700b2017-05-11 15:50:03 +0900507 networkType.toString());
508 throw new IllegalStateException(error);
509 }
510
sanghodc375372017-06-08 10:41:30 +0900511 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900512 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900513 osNode.intgBridge(),
daniel parkee8700b2017-05-11 15:50:03 +0900514 sBuilder.build(),
515 tBuilder.build(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900516 PRIORITY_EXTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900517 Constants.GW_COMMON_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900518 install);
519 }
520
Hyunsun Moon0d457362017-06-27 17:19:41 +0900521 private void setRulesToGatewayWithDstIp(OpenstackNode osNode, GroupId groupId,
522 String segmentId, IpAddress dstIp,
523 NetworkMode networkMode, boolean install) {
daniel parkee8700b2017-05-11 15:50:03 +0900524 TrafficSelector selector;
525 if (networkMode.equals(NetworkMode.VXLAN)) {
526 selector = DefaultTrafficSelector.builder()
527 .matchEthType(Ethernet.TYPE_IPV4)
528 .matchTunnelId(Long.valueOf(segmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900529 .matchIPDst(dstIp.getIp4Address().toIpPrefix())
daniel parkee8700b2017-05-11 15:50:03 +0900530 .build();
531 } else {
532 selector = DefaultTrafficSelector.builder()
533 .matchEthType(Ethernet.TYPE_IPV4)
534 .matchVlanId(VlanId.vlanId(segmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900535 .matchIPDst(dstIp.getIp4Address().toIpPrefix())
daniel parkee8700b2017-05-11 15:50:03 +0900536 .build();
537 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900538
539 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
540 .group(groupId)
541 .build();
542
sanghodc375372017-06-08 10:41:30 +0900543 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900544 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900545 osNode.intgBridge(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900546 selector,
547 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900548 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900549 ROUTING_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900550 install);
551 }
552
553 private class InternalRouterEventListener implements OpenstackRouterListener {
554
555 @Override
556 public boolean isRelevant(OpenstackRouterEvent event) {
557 // do not allow to proceed without leadership
558 NodeId leader = leadershipService.getLeader(appId.name());
559 return Objects.equals(localNodeId, leader);
560 }
561
562 // FIXME only one leader in the cluster should process
563 @Override
564 public void event(OpenstackRouterEvent event) {
565 switch (event.type()) {
566 case OPENSTACK_ROUTER_CREATED:
567 log.debug("Router(name:{}, ID:{}) is created",
568 event.subject().getName(),
569 event.subject().getId());
570 eventExecutor.execute(() -> routerUpdated(event.subject()));
571 break;
572 case OPENSTACK_ROUTER_UPDATED:
573 log.debug("Router(name:{}, ID:{}) is updated",
574 event.subject().getName(),
575 event.subject().getId());
576 eventExecutor.execute(() -> routerUpdated(event.subject()));
577 break;
578 case OPENSTACK_ROUTER_REMOVED:
579 log.debug("Router(name:{}, ID:{}) is removed",
580 event.subject().getName(),
581 event.subject().getId());
582 break;
583 case OPENSTACK_ROUTER_INTERFACE_ADDED:
584 log.debug("Router interface {} added to router {}",
585 event.routerIface().getPortId(),
586 event.routerIface().getId());
587 eventExecutor.execute(() -> routerIfaceAdded(
588 event.subject(),
589 event.routerIface()));
590 break;
591 case OPENSTACK_ROUTER_INTERFACE_UPDATED:
592 log.debug("Router interface {} on {} updated",
593 event.routerIface().getPortId(),
594 event.routerIface().getId());
595 break;
596 case OPENSTACK_ROUTER_INTERFACE_REMOVED:
597 log.debug("Router interface {} removed from router {}",
598 event.routerIface().getPortId(),
599 event.routerIface().getId());
600 eventExecutor.execute(() -> routerIfaceRemoved(
601 event.subject(),
602 event.routerIface()));
603 break;
604 case OPENSTACK_ROUTER_GATEWAY_ADDED:
605 case OPENSTACK_ROUTER_GATEWAY_REMOVED:
606 case OPENSTACK_FLOATING_IP_CREATED:
607 case OPENSTACK_FLOATING_IP_UPDATED:
608 case OPENSTACK_FLOATING_IP_REMOVED:
609 case OPENSTACK_FLOATING_IP_ASSOCIATED:
610 case OPENSTACK_FLOATING_IP_DISASSOCIATED:
611 default:
612 // do nothing for the other events
613 break;
614 }
615 }
616 }
617
618 private class InternalNodeEventListener implements OpenstackNodeListener {
619
620 @Override
621 public boolean isRelevant(OpenstackNodeEvent event) {
622 // do not allow to proceed without leadership
623 NodeId leader = leadershipService.getLeader(appId.name());
624 return Objects.equals(localNodeId, leader);
625 }
626
627 @Override
628 public void event(OpenstackNodeEvent event) {
629 OpenstackNode osNode = event.subject();
630
631 switch (event.type()) {
Hyunsun Moon0d457362017-06-27 17:19:41 +0900632 case OPENSTACK_NODE_COMPLETE:
633 case OPENSTACK_NODE_INCOMPLETE:
Hyunsun Moon44aac662017-02-18 02:07:01 +0900634 eventExecutor.execute(() -> {
Hyunsun Moon0e058f22017-04-19 17:00:52 +0900635 log.info("Reconfigure routers for {}", osNode.hostname());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900636 reconfigureRouters();
637 });
638 break;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900639 case OPENSTACK_NODE_CREATED:
640 case OPENSTACK_NODE_UPDATED:
641 case OPENSTACK_NODE_REMOVED:
Hyunsun Moon44aac662017-02-18 02:07:01 +0900642 default:
643 break;
644 }
645 }
646
647 private void reconfigureRouters() {
648 osRouterService.routers().forEach(osRouter -> {
649 routerUpdated(osRouter);
650 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
651 routerIfaceAdded(osRouter, iface);
652 });
653 });
654 }
655 }
656}