blob: bde5efe595cd720437fbef3d3044b5e34daadfb3 [file] [log] [blame]
Hyunsun Moon44aac662017-02-18 02:07:01 +09001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Hyunsun Moon44aac662017-02-18 02:07:01 +09003 *
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;
Daniel Park613ac372018-06-28 14:30:11 +090020import com.google.common.collect.Sets;
Hyunsun Moon44aac662017-02-18 02:07:01 +090021import org.onlab.packet.Ethernet;
22import org.onlab.packet.IPv4;
23import org.onlab.packet.IpAddress;
24import org.onlab.packet.IpPrefix;
sangho072c4dd2017-05-17 10:45:21 +090025import org.onlab.packet.MacAddress;
daniel parkee8700b2017-05-11 15:50:03 +090026import org.onlab.packet.VlanId;
sanghoe765ce22017-06-23 17:54:57 +090027import org.onlab.util.Tools;
28import org.onosproject.cfg.ComponentConfigService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090029import org.onosproject.cluster.ClusterService;
30import org.onosproject.cluster.LeadershipService;
31import org.onosproject.cluster.NodeId;
32import org.onosproject.core.ApplicationId;
33import org.onosproject.core.CoreService;
sangho072c4dd2017-05-17 10:45:21 +090034import org.onosproject.mastership.MastershipService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090035import org.onosproject.net.DeviceId;
36import org.onosproject.net.PortNumber;
sangho072c4dd2017-05-17 10:45:21 +090037import org.onosproject.net.device.DeviceService;
38import org.onosproject.net.driver.DriverService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090039import org.onosproject.net.flow.DefaultTrafficSelector;
40import org.onosproject.net.flow.DefaultTrafficTreatment;
41import org.onosproject.net.flow.TrafficSelector;
42import org.onosproject.net.flow.TrafficTreatment;
sangho072c4dd2017-05-17 10:45:21 +090043import org.onosproject.net.flow.instructions.ExtensionTreatment;
Hyunsun Moon44aac662017-02-18 02:07:01 +090044import org.onosproject.openstacknetworking.api.Constants;
daniel park576969a2018-03-09 07:07:41 +090045import org.onosproject.openstacknetworking.api.ExternalPeerRouter;
sangho072c4dd2017-05-17 10:45:21 +090046import org.onosproject.openstacknetworking.api.InstancePort;
47import org.onosproject.openstacknetworking.api.InstancePortEvent;
48import org.onosproject.openstacknetworking.api.InstancePortListener;
49import org.onosproject.openstacknetworking.api.InstancePortService;
sanghodc375372017-06-08 10:41:30 +090050import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
daniel park32b42202018-03-14 16:53:44 +090051import org.onosproject.openstacknetworking.api.OpenstackNetworkAdminService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090052import org.onosproject.openstacknetworking.api.OpenstackRouterEvent;
53import org.onosproject.openstacknetworking.api.OpenstackRouterListener;
54import org.onosproject.openstacknetworking.api.OpenstackRouterService;
Jian Li26949762018-03-30 15:46:37 +090055import org.onosproject.openstacknetworking.util.RulePopulatorUtil;
Hyunsun Moon0d457362017-06-27 17:19:41 +090056import org.onosproject.openstacknode.api.OpenstackNode;
Hyunsun Moon0d457362017-06-27 17:19:41 +090057import org.onosproject.openstacknode.api.OpenstackNodeEvent;
58import org.onosproject.openstacknode.api.OpenstackNodeListener;
59import org.onosproject.openstacknode.api.OpenstackNodeService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090060import org.openstack4j.model.network.ExternalGateway;
61import org.openstack4j.model.network.Network;
daniel parkee8700b2017-05-11 15:50:03 +090062import org.openstack4j.model.network.NetworkType;
Hyunsun Moon44aac662017-02-18 02:07:01 +090063import org.openstack4j.model.network.Router;
64import org.openstack4j.model.network.RouterInterface;
65import org.openstack4j.model.network.Subnet;
sanghoe765ce22017-06-23 17:54:57 +090066import org.osgi.service.component.ComponentContext;
Ray Milkeyd84f89b2018-08-17 14:54:17 -070067import org.osgi.service.component.annotations.Activate;
68import org.osgi.service.component.annotations.Component;
69import org.osgi.service.component.annotations.Deactivate;
70import org.osgi.service.component.annotations.Modified;
71import org.osgi.service.component.annotations.Reference;
72import org.osgi.service.component.annotations.ReferenceCardinality;
Hyunsun Moon44aac662017-02-18 02:07:01 +090073import org.slf4j.Logger;
74import org.slf4j.LoggerFactory;
75
sanghoe765ce22017-06-23 17:54:57 +090076import java.util.Dictionary;
Hyunsun Moon44aac662017-02-18 02:07:01 +090077import java.util.Objects;
sangho072c4dd2017-05-17 10:45:21 +090078import java.util.Optional;
Hyunsun Moon44aac662017-02-18 02:07:01 +090079import java.util.Set;
80import java.util.concurrent.ExecutorService;
81import java.util.stream.Collectors;
82
83import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
84import static org.onlab.util.Tools.groupedThreads;
sangho072c4dd2017-05-17 10:45:21 +090085import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_EXTERNAL_ROUTER_MAC;
86import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_GATEWAY_MAC;
sangho072c4dd2017-05-17 10:45:21 +090087import static org.onosproject.openstacknetworking.api.Constants.GW_COMMON_TABLE;
88import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
daniel park796c2eb2018-03-22 17:01:51 +090089import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ADMIN_RULE;
sangho072c4dd2017-05-17 10:45:21 +090090import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_EXTERNAL_ROUTING_RULE;
91import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ICMP_RULE;
92import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_INTERNAL_ROUTING_RULE;
sanghoe765ce22017-06-23 17:54:57 +090093import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_STATEFUL_SNAT_RULE;
sangho072c4dd2017-05-17 10:45:21 +090094import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_SWITCHING_RULE;
95import static org.onosproject.openstacknetworking.api.Constants.ROUTING_TABLE;
Jian Li8abf2fe2018-06-12 18:42:30 +090096import static org.onosproject.openstacknetworking.api.Constants.STAT_OUTBOUND_TABLE;
Jian Lic2403592018-07-18 12:56:45 +090097import static org.onosproject.openstacknetworking.api.InstancePort.State.ACTIVE;
Ray Milkey8e406512018-10-24 15:56:50 -070098import static org.onosproject.openstacknetworking.impl.OsgiPropertyConstants.USE_STATEFUL_SNAT;
99import static org.onosproject.openstacknetworking.impl.OsgiPropertyConstants.USE_STATEFUL_SNAT_DEFAULT;
Jian Li2d68c192018-12-13 15:52:59 +0900100import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.tunnelPortNumByNetType;
Jian Li26949762018-03-30 15:46:37 +0900101import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900102import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
103import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
Jian Li32b03622018-11-06 17:54:24 +0900104import static org.openstack4j.model.network.NetworkType.FLAT;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900105
106/**
107 * Handles OpenStack router events.
108 */
Ray Milkey8e406512018-10-24 15:56:50 -0700109@Component(
110 immediate = true,
111 property = {
112 USE_STATEFUL_SNAT + ":Boolean=" + USE_STATEFUL_SNAT_DEFAULT
113 }
114)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900115public class OpenstackRoutingHandler {
116
117 private final Logger log = LoggerFactory.getLogger(getClass());
118
119 private static final String MSG_ENABLED = "Enabled ";
120 private static final String MSG_DISABLED = "Disabled ";
daniel parkee8700b2017-05-11 15:50:03 +0900121 private static final String ERR_UNSUPPORTED_NET_TYPE = "Unsupported network type";
sanghoe765ce22017-06-23 17:54:57 +0900122
Jian Li4d138702018-11-27 17:25:28 +0900123 private static final int VM_PREFIX = 32;
124
Ray Milkey8e406512018-10-24 15:56:50 -0700125 /** Use Stateful SNAT for source NATing. */
126 private boolean useStatefulSnat = USE_STATEFUL_SNAT_DEFAULT;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900127
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700128 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900129 protected CoreService coreService;
130
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700131 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900132 protected LeadershipService leadershipService;
133
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700134 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900135 protected ClusterService clusterService;
136
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700137 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900138 protected OpenstackNodeService osNodeService;
139
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700140 @Reference(cardinality = ReferenceCardinality.MANDATORY)
daniel park32b42202018-03-14 16:53:44 +0900141 protected OpenstackNetworkAdminService osNetworkAdminService;
142
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700143 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900144 protected OpenstackRouterService osRouterService;
145
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700146 @Reference(cardinality = ReferenceCardinality.MANDATORY)
sangho072c4dd2017-05-17 10:45:21 +0900147 protected InstancePortService instancePortService;
148
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700149 @Reference(cardinality = ReferenceCardinality.MANDATORY)
sangho072c4dd2017-05-17 10:45:21 +0900150 protected DeviceService deviceService;
151
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700152 @Reference(cardinality = ReferenceCardinality.MANDATORY)
sanghodc375372017-06-08 10:41:30 +0900153 protected OpenstackFlowRuleService osFlowRuleService;
154
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700155 @Reference(cardinality = ReferenceCardinality.MANDATORY)
sangho072c4dd2017-05-17 10:45:21 +0900156 protected MastershipService mastershipService;
157
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700158 @Reference(cardinality = ReferenceCardinality.MANDATORY)
sangho072c4dd2017-05-17 10:45:21 +0900159 protected DriverService driverService;
160
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700161 @Reference(cardinality = ReferenceCardinality.MANDATORY)
sanghoe765ce22017-06-23 17:54:57 +0900162 protected ComponentConfigService configService;
163
Hyunsun Moon44aac662017-02-18 02:07:01 +0900164 private final ExecutorService eventExecutor = newSingleThreadScheduledExecutor(
165 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
166 private final OpenstackNodeListener osNodeListener = new InternalNodeEventListener();
167 private final OpenstackRouterListener osRouterListener = new InternalRouterEventListener();
sangho072c4dd2017-05-17 10:45:21 +0900168 private final InstancePortListener instancePortListener = new InternalInstancePortListener();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900169
170 private ApplicationId appId;
171 private NodeId localNodeId;
172
173 @Activate
174 protected void activate() {
175 appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
176 localNodeId = clusterService.getLocalNode().id();
177 leadershipService.runForLeadership(appId.name());
178 osNodeService.addListener(osNodeListener);
179 osRouterService.addListener(osRouterListener);
sangho072c4dd2017-05-17 10:45:21 +0900180 instancePortService.addListener(instancePortListener);
sanghoe765ce22017-06-23 17:54:57 +0900181 configService.registerProperties(getClass());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900182
183 log.info("Started");
184 }
185
186 @Deactivate
187 protected void deactivate() {
188 osRouterService.removeListener(osRouterListener);
189 osNodeService.removeListener(osNodeListener);
sangho072c4dd2017-05-17 10:45:21 +0900190 instancePortService.removeListener(instancePortListener);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900191 leadershipService.withdraw(appId.name());
sanghoe765ce22017-06-23 17:54:57 +0900192 configService.unregisterProperties(getClass(), false);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900193 eventExecutor.shutdown();
194
195 log.info("Stopped");
196 }
197
sanghoe765ce22017-06-23 17:54:57 +0900198 @Modified
199 protected void modified(ComponentContext context) {
200 Dictionary<?, ?> properties = context.getProperties();
201 Boolean flag;
202
Ray Milkey8e406512018-10-24 15:56:50 -0700203 flag = Tools.isPropertyEnabled(properties, USE_STATEFUL_SNAT);
sanghoe765ce22017-06-23 17:54:57 +0900204 if (flag == null) {
205 log.info("useStatefulSnat is not configured, " +
206 "using current value of {}", useStatefulSnat);
207 } else {
208 useStatefulSnat = flag;
209 log.info("Configured. useStatefulSnat is {}",
210 useStatefulSnat ? "enabled" : "disabled");
211 }
212
213 resetSnatRules();
214 }
215
Hyunsun Moon44aac662017-02-18 02:07:01 +0900216 private void routerUpdated(Router osRouter) {
217 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
Frank Wang245a6822017-06-14 09:51:35 +0800218 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
Jian Li5ecfd1a2018-12-10 11:41:03 +0900219 Network network = osNetworkAdminService.network(
220 osNetworkAdminService.subnet(iface.getSubnetId())
Frank Wang245a6822017-06-14 09:51:35 +0800221 .getNetworkId());
Jian Li5ecfd1a2018-12-10 11:41:03 +0900222 setRouterAdminRules(network.getProviderSegID(),
223 network.getNetworkType(), !osRouter.isAdminStateUp());
Frank Wang245a6822017-06-14 09:51:35 +0800224 });
225
Jian Li5ecfd1a2018-12-10 11:41:03 +0900226 ExternalPeerRouter externalPeerRouter =
227 osNetworkAdminService.externalPeerRouter(exGateway);
Jian Li5e2ad4a2018-07-16 13:40:53 +0900228 VlanId vlanId = externalPeerRouter == null ? VlanId.NONE : externalPeerRouter.vlanId();
daniel park576969a2018-03-09 07:07:41 +0900229
Hyunsun Moon44aac662017-02-18 02:07:01 +0900230 if (exGateway == null) {
Daniel Park613ac372018-06-28 14:30:11 +0900231 deleteUnassociatedExternalPeerRouter();
Jian Li5ecfd1a2018-12-10 11:41:03 +0900232 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface ->
233 setSourceNat(iface, false));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900234 } else {
daniel park32b42202018-03-14 16:53:44 +0900235 osNetworkAdminService.deriveExternalPeerRouterMac(exGateway, osRouter, vlanId);
daniel park576969a2018-03-09 07:07:41 +0900236 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface ->
237 setSourceNat(iface, exGateway.isEnableSnat()));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900238 }
239 }
240
Daniel Park613ac372018-06-28 14:30:11 +0900241 private void deleteUnassociatedExternalPeerRouter() {
242 log.trace("Deleting unassociated external peer router");
243
244 try {
245 Set<String> routerIps = Sets.newConcurrentHashSet();
246
247 osRouterService.routers().stream()
248 .filter(router -> getGatewayIpAddress(router) != null)
249 .map(router -> getGatewayIpAddress(router).toString())
250 .forEach(routerIps::add);
251
252 osNetworkAdminService.externalPeerRouters().stream()
253 .filter(externalPeerRouter ->
Jian Li5e2ad4a2018-07-16 13:40:53 +0900254 !routerIps.contains(externalPeerRouter.ipAddress().toString()))
Daniel Park613ac372018-06-28 14:30:11 +0900255 .forEach(externalPeerRouter -> {
256 osNetworkAdminService
Jian Li5ecfd1a2018-12-10 11:41:03 +0900257 .deleteExternalPeerRouter(
258 externalPeerRouter.ipAddress().toString());
Daniel Park613ac372018-06-28 14:30:11 +0900259 log.trace("Deleted unassociated external peer router {}",
Jian Li5e2ad4a2018-07-16 13:40:53 +0900260 externalPeerRouter.ipAddress().toString());
Daniel Park613ac372018-06-28 14:30:11 +0900261 });
262 } catch (Exception e) {
263 log.error("Exception occurred because of {}", e.toString());
264 }
265 }
266
Frank Wang245a6822017-06-14 09:51:35 +0800267 private void routerRemove(Router osRouter) {
268 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
Jian Li5ecfd1a2018-12-10 11:41:03 +0900269 Network network = osNetworkAdminService.network(
270 osNetworkAdminService.subnet(iface.getSubnetId())
Frank Wang245a6822017-06-14 09:51:35 +0800271 .getNetworkId());
272 setRouterAdminRules(network.getProviderSegID(), network.getNetworkType(), false);
273 });
274 }
275
Hyunsun Moon44aac662017-02-18 02:07:01 +0900276 private void routerIfaceAdded(Router osRouter, RouterInterface osRouterIface) {
Jian Liedc8b762018-03-22 15:42:00 +0900277 Subnet osSubnet = osNetworkAdminService.subnet(osRouterIface.getSubnetId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900278 if (osSubnet == null) {
279 final String error = String.format(
Jian Li71670d12018-03-02 21:31:07 +0900280 "Failed to set flows for router %s: subnet %s does not exist",
Hyunsun Moon44aac662017-02-18 02:07:01 +0900281 osRouterIface.getId(),
282 osRouterIface.getSubnetId());
283 throw new IllegalStateException(error);
284 }
Frank Wang245a6822017-06-14 09:51:35 +0800285
286 if (!osRouter.isAdminStateUp()) {
Jian Liedc8b762018-03-22 15:42:00 +0900287 Network network = osNetworkAdminService.network(osSubnet.getNetworkId());
Jian Li5ecfd1a2018-12-10 11:41:03 +0900288 setRouterAdminRules(network.getProviderSegID(),
289 network.getNetworkType(), true);
Frank Wang245a6822017-06-14 09:51:35 +0800290 }
291
Hyunsun Moon44aac662017-02-18 02:07:01 +0900292 setInternalRoutes(osRouter, osSubnet, true);
Daniel Park51f9d1e2018-10-26 13:39:09 +0900293 setGatewayIcmp(osSubnet, osRouter, true);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900294 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
295 if (exGateway != null && exGateway.isEnableSnat()) {
daniel park576969a2018-03-09 07:07:41 +0900296 setSourceNat(osRouterIface, true);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900297 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900298 log.info("Connected subnet({}) to {}", osSubnet.getCidr(), osRouter.getName());
299 }
300
301 private void routerIfaceRemoved(Router osRouter, RouterInterface osRouterIface) {
Jian Liedc8b762018-03-22 15:42:00 +0900302 Subnet osSubnet = osNetworkAdminService.subnet(osRouterIface.getSubnetId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900303 if (osSubnet == null) {
304 final String error = String.format(
Jian Li71670d12018-03-02 21:31:07 +0900305 "Failed to set flows for router %s: subnet %s does not exist",
Hyunsun Moon44aac662017-02-18 02:07:01 +0900306 osRouterIface.getId(),
307 osRouterIface.getSubnetId());
308 throw new IllegalStateException(error);
309 }
310
Frank Wang245a6822017-06-14 09:51:35 +0800311 if (!osRouter.isAdminStateUp()) {
Jian Liedc8b762018-03-22 15:42:00 +0900312 Network network = osNetworkAdminService.network(osSubnet.getNetworkId());
Jian Li5ecfd1a2018-12-10 11:41:03 +0900313 setRouterAdminRules(network.getProviderSegID(),
314 network.getNetworkType(), false);
Frank Wang245a6822017-06-14 09:51:35 +0800315 }
316
Hyunsun Moon44aac662017-02-18 02:07:01 +0900317 setInternalRoutes(osRouter, osSubnet, false);
Daniel Park51f9d1e2018-10-26 13:39:09 +0900318 setGatewayIcmp(osSubnet, osRouter, false);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900319 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
320 if (exGateway != null && exGateway.isEnableSnat()) {
daniel park576969a2018-03-09 07:07:41 +0900321 setSourceNat(osRouterIface, false);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900322 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900323 log.info("Disconnected subnet({}) from {}", osSubnet.getCidr(), osRouter.getName());
324 }
325
daniel park576969a2018-03-09 07:07:41 +0900326 private void setSourceNat(RouterInterface routerIface, boolean install) {
Jian Liedc8b762018-03-22 15:42:00 +0900327 Subnet osSubnet = osNetworkAdminService.subnet(routerIface.getSubnetId());
328 Network osNet = osNetworkAdminService.network(osSubnet.getNetworkId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900329
Hyunsun Moon0d457362017-06-27 17:19:41 +0900330 osNodeService.completeNodes(COMPUTE).forEach(cNode -> {
331 setRulesToGateway(cNode, osNet.getProviderSegID(),
332 IpPrefix.valueOf(osSubnet.getCidr()), osNet.getNetworkType(),
333 install);
334 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900335
sanghoe765ce22017-06-23 17:54:57 +0900336 if (useStatefulSnat) {
337 setStatefulSnatRules(routerIface, install);
338 } else {
339 setReactiveSnatRules(routerIface, install);
340 }
341
342 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
343 log.info(updateStr + "external access for subnet({})", osSubnet.getCidr());
344 }
345
346 private void setStatefulSnatRules(RouterInterface routerIface, boolean install) {
Jian Liedc8b762018-03-22 15:42:00 +0900347 Subnet osSubnet = osNetworkAdminService.subnet(routerIface.getSubnetId());
348 Network osNet = osNetworkAdminService.network(osSubnet.getNetworkId());
sanghoe765ce22017-06-23 17:54:57 +0900349
Jian Li32b03622018-11-06 17:54:24 +0900350 if (osNet.getNetworkType() == FLAT) {
daniel park796c2eb2018-03-22 17:01:51 +0900351 return;
352 }
353
sanghoe765ce22017-06-23 17:54:57 +0900354 Optional<Router> osRouter = osRouterService.routers().stream()
355 .filter(router -> osRouterService.routerInterfaces(routerIface.getId()) != null)
356 .findAny();
357
358 if (!osRouter.isPresent()) {
359 log.error("Cannot find a router for router interface {} ", routerIface);
360 return;
361 }
362 IpAddress natAddress = getGatewayIpAddress(osRouter.get());
sangho072c4dd2017-05-17 10:45:21 +0900363 if (natAddress == null) {
364 return;
365 }
Jian Liedc8b762018-03-22 15:42:00 +0900366 String netId = osNetworkAdminService.subnet(routerIface.getSubnetId()).getNetworkId();
sangho072c4dd2017-05-17 10:45:21 +0900367
368 osNodeService.completeNodes(OpenstackNode.NodeType.GATEWAY)
369 .forEach(gwNode -> {
daniel park576969a2018-03-09 07:07:41 +0900370 instancePortService.instancePorts(netId)
Jian Lic2403592018-07-18 12:56:45 +0900371 .stream()
372 .filter(port -> port.state() == ACTIVE)
daniel park576969a2018-03-09 07:07:41 +0900373 .forEach(port -> setRulesForSnatIngressRule(gwNode.intgBridge(),
sangho072c4dd2017-05-17 10:45:21 +0900374 Long.parseLong(osNet.getProviderSegID()),
Jian Li4d138702018-11-27 17:25:28 +0900375 IpPrefix.valueOf(port.ipAddress(), VM_PREFIX),
sangho072c4dd2017-05-17 10:45:21 +0900376 port.deviceId(),
Jian Li2d68c192018-12-13 15:52:59 +0900377 osNet.getNetworkType(),
sangho072c4dd2017-05-17 10:45:21 +0900378 install));
379
380 setOvsNatIngressRule(gwNode.intgBridge(),
Jian Li4d138702018-11-27 17:25:28 +0900381 IpPrefix.valueOf(natAddress, VM_PREFIX),
sangho072c4dd2017-05-17 10:45:21 +0900382 Constants.DEFAULT_EXTERNAL_ROUTER_MAC, install);
383 setOvsNatEgressRule(gwNode.intgBridge(),
384 natAddress, Long.parseLong(osNet.getProviderSegID()),
385 gwNode.patchPortNum(), install);
386 });
sanghoe765ce22017-06-23 17:54:57 +0900387 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900388
sanghoe765ce22017-06-23 17:54:57 +0900389 private void setReactiveSnatRules(RouterInterface routerIface, boolean install) {
Jian Liedc8b762018-03-22 15:42:00 +0900390 Subnet osSubnet = osNetworkAdminService.subnet(routerIface.getSubnetId());
391 Network osNet = osNetworkAdminService.network(osSubnet.getNetworkId());
sanghoe765ce22017-06-23 17:54:57 +0900392
393 osNodeService.completeNodes(GATEWAY)
394 .forEach(gwNode -> setRulesToController(
395 gwNode.intgBridge(),
396 osNet.getProviderSegID(),
397 IpPrefix.valueOf(osSubnet.getCidr()),
398 osNet.getNetworkType(),
399 install));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900400 }
401
sangho072c4dd2017-05-17 10:45:21 +0900402 private IpAddress getGatewayIpAddress(Router osRouter) {
403
Daniel Park613ac372018-06-28 14:30:11 +0900404 if (osRouter.getExternalGatewayInfo() == null) {
405 return null;
406 }
Jian Li5ecfd1a2018-12-10 11:41:03 +0900407 String extNetId = osNetworkAdminService.network(
408 osRouter.getExternalGatewayInfo().getNetworkId()).getId();
Jian Liedc8b762018-03-22 15:42:00 +0900409 Optional<Subnet> extSubnet = osNetworkAdminService.subnets().stream()
sangho072c4dd2017-05-17 10:45:21 +0900410 .filter(subnet -> subnet.getNetworkId().equals(extNetId))
411 .findAny();
412
413 if (!extSubnet.isPresent()) {
414 log.error("Cannot find externel subnet for the router");
415 return null;
416 }
417
418 return IpAddress.valueOf(extSubnet.get().getGateway());
419 }
420
sanghoe765ce22017-06-23 17:54:57 +0900421 private void resetSnatRules() {
422 if (useStatefulSnat) {
423 osRouterService.routerInterfaces().forEach(
424 routerIface -> {
425 setReactiveSnatRules(routerIface, false);
426 setStatefulSnatRules(routerIface, true);
427 }
428 );
429 } else {
430 osRouterService.routerInterfaces().forEach(
431 routerIface -> {
432 setStatefulSnatRules(routerIface, false);
433 setReactiveSnatRules(routerIface, true);
434 }
435 );
436 }
437 }
438
Daniel Park51f9d1e2018-10-26 13:39:09 +0900439 private void setGatewayIcmp(Subnet osSubnet, Router osRouter, boolean install) {
Jian Li4d138702018-11-27 17:25:28 +0900440 OpenstackNode srcNatGw = osNodeService.completeNodes(GATEWAY)
441 .stream().findFirst().orElse(null);
daniel parkb5817102018-02-15 00:18:51 +0900442
Jian Li4d138702018-11-27 17:25:28 +0900443 if (srcNatGw == null) {
daniel parkb5817102018-02-15 00:18:51 +0900444 return;
445 }
446
Hyunsun Moon44aac662017-02-18 02:07:01 +0900447 if (Strings.isNullOrEmpty(osSubnet.getGateway())) {
448 // do nothing if no gateway is set
449 return;
450 }
451
452 // take ICMP request to a subnet gateway through gateway node group
Jian Li4d138702018-11-27 17:25:28 +0900453 Network net = osNetworkAdminService.network(osSubnet.getNetworkId());
Daniel Park51f9d1e2018-10-26 13:39:09 +0900454 Set<Subnet> routableSubnets = routableSubnets(osRouter, osSubnet.getId());
455
Jian Li4d138702018-11-27 17:25:28 +0900456 switch (net.getNetworkType()) {
daniel parkee8700b2017-05-11 15:50:03 +0900457 case VXLAN:
Jian Li4d138702018-11-27 17:25:28 +0900458 setGatewayIcmpForVxlan(osSubnet, srcNatGw, net, routableSubnets, install);
daniel parkee8700b2017-05-11 15:50:03 +0900459 break;
Jian Li2d68c192018-12-13 15:52:59 +0900460 case GRE:
461 setGatewayIcmpForGre(osSubnet, srcNatGw, net, routableSubnets, install);
462 break;
daniel parkee8700b2017-05-11 15:50:03 +0900463 case VLAN:
Jian Li4d138702018-11-27 17:25:28 +0900464 setGatewayIcmpForVlan(osSubnet, srcNatGw, net, routableSubnets, install);
daniel parkee8700b2017-05-11 15:50:03 +0900465 break;
466 default:
Jian Li4d138702018-11-27 17:25:28 +0900467 final String error = String.format("%s %s", ERR_UNSUPPORTED_NET_TYPE,
468 net.getNetworkType().toString());
daniel parkee8700b2017-05-11 15:50:03 +0900469 throw new IllegalStateException(error);
470 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900471
472 IpAddress gatewayIp = IpAddress.valueOf(osSubnet.getGateway());
daniel park576969a2018-03-09 07:07:41 +0900473 osNodeService.completeNodes(GATEWAY).forEach(gNode ->
Hyunsun Moon0d457362017-06-27 17:19:41 +0900474 setGatewayIcmpRule(
475 gatewayIp,
476 gNode.intgBridge(),
daniel park576969a2018-03-09 07:07:41 +0900477 install));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900478
479 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
480 log.debug(updateStr + "ICMP to {}", osSubnet.getGateway());
481 }
482
Jian Li4d138702018-11-27 17:25:28 +0900483 private void setGatewayIcmpForVxlan(Subnet osSubnet,
484 OpenstackNode srcNatGw,
485 Network network,
486 Set<Subnet> routableSubnets,
487 boolean install) {
488 osNodeService.completeNodes(COMPUTE).stream()
489 .filter(cNode -> cNode.dataIp() != null)
490 .forEach(cNode -> setRulesToGatewayWithRoutableSubnets(
491 cNode,
492 srcNatGw,
493 network.getProviderSegID(),
494 osSubnet,
495 routableSubnets,
Jian Li2d68c192018-12-13 15:52:59 +0900496 NetworkType.VXLAN,
497 install));
498 }
499
500 private void setGatewayIcmpForGre(Subnet osSubnet,
501 OpenstackNode srcNatGw,
502 Network network,
503 Set<Subnet> routableSubnets,
504 boolean install) {
505 osNodeService.completeNodes(COMPUTE).stream()
506 .filter(cNode -> cNode.dataIp() != null)
507 .forEach(cNode -> setRulesToGatewayWithRoutableSubnets(
508 cNode,
509 srcNatGw,
510 network.getProviderSegID(),
511 osSubnet,
512 routableSubnets,
513 NetworkType.GRE,
Jian Li4d138702018-11-27 17:25:28 +0900514 install));
515 }
516
517 private void setGatewayIcmpForVlan(Subnet osSubnet,
518 OpenstackNode srcNatGw,
519 Network network,
520 Set<Subnet> routableSubnets,
521 boolean install) {
522 osNodeService.completeNodes(COMPUTE).stream()
523 .filter(cNode -> cNode.vlanPortNum() != null)
524 .forEach(cNode -> setRulesToGatewayWithRoutableSubnets(
525 cNode,
526 srcNatGw,
527 network.getProviderSegID(),
528 osSubnet,
529 routableSubnets,
Jian Li2d68c192018-12-13 15:52:59 +0900530 NetworkType.VLAN,
Jian Li4d138702018-11-27 17:25:28 +0900531 install));
532 }
533
Hyunsun Moon44aac662017-02-18 02:07:01 +0900534 private void setInternalRoutes(Router osRouter, Subnet updatedSubnet, boolean install) {
Jian Liedc8b762018-03-22 15:42:00 +0900535 Network updatedNetwork = osNetworkAdminService.network(updatedSubnet.getNetworkId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900536 Set<Subnet> routableSubnets = routableSubnets(osRouter, updatedSubnet.getId());
Jian Lib6969502018-10-30 20:38:07 +0900537 String updatedSegmentId = getSegmentId(updatedSubnet);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900538
539 // installs rule from/to my subnet intentionally to fix ICMP failure
540 // to my subnet gateway if no external gateway added to the router
Hyunsun Moon0d457362017-06-27 17:19:41 +0900541 osNodeService.completeNodes(COMPUTE).forEach(cNode -> {
542 setInternalRouterRules(
543 cNode.intgBridge(),
Jian Lib6969502018-10-30 20:38:07 +0900544 updatedSegmentId,
545 updatedSegmentId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900546 IpPrefix.valueOf(updatedSubnet.getCidr()),
547 IpPrefix.valueOf(updatedSubnet.getCidr()),
548 updatedNetwork.getNetworkType(),
549 install
550 );
Hyunsun Moon44aac662017-02-18 02:07:01 +0900551
Hyunsun Moon0d457362017-06-27 17:19:41 +0900552 routableSubnets.forEach(subnet -> {
553 setInternalRouterRules(
554 cNode.intgBridge(),
Jian Lib6969502018-10-30 20:38:07 +0900555 updatedSegmentId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900556 getSegmentId(subnet),
557 IpPrefix.valueOf(updatedSubnet.getCidr()),
558 IpPrefix.valueOf(subnet.getCidr()),
559 updatedNetwork.getNetworkType(),
560 install
561 );
562 setInternalRouterRules(
563 cNode.intgBridge(),
564 getSegmentId(subnet),
Jian Lib6969502018-10-30 20:38:07 +0900565 updatedSegmentId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900566 IpPrefix.valueOf(subnet.getCidr()),
567 IpPrefix.valueOf(updatedSubnet.getCidr()),
568 updatedNetwork.getNetworkType(),
569 install
570 );
571 });
572 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900573
daniel parkee8700b2017-05-11 15:50:03 +0900574
Hyunsun Moon44aac662017-02-18 02:07:01 +0900575 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
576 routableSubnets.forEach(subnet -> log.debug(
577 updateStr + "route between subnet:{} and subnet:{}",
578 subnet.getCidr(),
579 updatedSubnet.getCidr()));
580 }
581
582 private Set<Subnet> routableSubnets(Router osRouter, String osSubnetId) {
583 Set<Subnet> osSubnets = osRouterService.routerInterfaces(osRouter.getId())
584 .stream()
585 .filter(iface -> !Objects.equals(iface.getSubnetId(), osSubnetId))
Jian Liedc8b762018-03-22 15:42:00 +0900586 .map(iface -> osNetworkAdminService.subnet(iface.getSubnetId()))
Hyunsun Moon44aac662017-02-18 02:07:01 +0900587 .collect(Collectors.toSet());
588 return ImmutableSet.copyOf(osSubnets);
589 }
590
daniel parkee8700b2017-05-11 15:50:03 +0900591 private String getSegmentId(Subnet osSubnet) {
Jian Liedc8b762018-03-22 15:42:00 +0900592 return osNetworkAdminService.network(osSubnet.getNetworkId()).getProviderSegID();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900593 }
594
595 private void setGatewayIcmpRule(IpAddress gatewayIp, DeviceId deviceId, boolean install) {
596 TrafficSelector selector = DefaultTrafficSelector.builder()
597 .matchEthType(Ethernet.TYPE_IPV4)
598 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900599 .matchIPDst(gatewayIp.getIp4Address().toIpPrefix())
Hyunsun Moon44aac662017-02-18 02:07:01 +0900600 .build();
601
602 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Jian Li4d5c5c32018-04-02 16:38:18 +0900603 .punt()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900604 .build();
605
sanghodc375372017-06-08 10:41:30 +0900606 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900607 appId,
608 deviceId,
609 selector,
610 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900611 PRIORITY_ICMP_RULE,
sanghodc375372017-06-08 10:41:30 +0900612 Constants.GW_COMMON_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900613 install);
614 }
615
Jian Li4d138702018-11-27 17:25:28 +0900616 private void setInternalRouterRules(DeviceId deviceId, String srcSegId, String dstSegId,
daniel parkee8700b2017-05-11 15:50:03 +0900617 IpPrefix srcSubnet, IpPrefix dstSubnet,
618 NetworkType networkType, boolean install) {
Jian Li4d138702018-11-27 17:25:28 +0900619
daniel parkee8700b2017-05-11 15:50:03 +0900620 switch (networkType) {
621 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900622 case GRE:
623 setInternalRouterRulesForTunnel(deviceId, srcSegId, dstSegId,
Jian Li4d138702018-11-27 17:25:28 +0900624 srcSubnet, dstSubnet, install);
daniel parkee8700b2017-05-11 15:50:03 +0900625 break;
626 case VLAN:
Jian Li4d138702018-11-27 17:25:28 +0900627 setInternalRouterRulesForVlan(deviceId, srcSegId, dstSegId,
628 srcSubnet, dstSubnet, install);
daniel parkee8700b2017-05-11 15:50:03 +0900629 break;
630 default:
Jian Li4d138702018-11-27 17:25:28 +0900631 final String error = String.format("%s %s", ERR_UNSUPPORTED_NET_TYPE,
632 networkType.toString());
daniel parkee8700b2017-05-11 15:50:03 +0900633 throw new IllegalStateException(error);
634 }
635
Hyunsun Moon44aac662017-02-18 02:07:01 +0900636 }
637
Jian Li2d68c192018-12-13 15:52:59 +0900638 private void setInternalRouterRulesForTunnel(DeviceId deviceId,
639 String srcSegmentId,
640 String dstSegmentId,
641 IpPrefix srcSubnet,
642 IpPrefix dstSubnet,
643 boolean install) {
Jian Li4d138702018-11-27 17:25:28 +0900644 TrafficSelector selector;
645 TrafficTreatment treatment;
646 selector = DefaultTrafficSelector.builder()
647 .matchEthType(Ethernet.TYPE_IPV4)
648 .matchTunnelId(Long.parseLong(srcSegmentId))
649 .matchIPSrc(srcSubnet.getIp4Prefix())
650 .matchIPDst(dstSubnet.getIp4Prefix())
651 .build();
652
653 treatment = DefaultTrafficTreatment.builder()
654 .setTunnelId(Long.parseLong(dstSegmentId))
655 .transition(STAT_OUTBOUND_TABLE)
656 .build();
657
658 osFlowRuleService.setRule(
659 appId,
660 deviceId,
661 selector,
662 treatment,
663 PRIORITY_INTERNAL_ROUTING_RULE,
664 ROUTING_TABLE,
665 install);
666
667 selector = DefaultTrafficSelector.builder()
668 .matchEthType(Ethernet.TYPE_IPV4)
669 .matchTunnelId(Long.parseLong(dstSegmentId))
670 .matchIPSrc(srcSubnet.getIp4Prefix())
671 .matchIPDst(dstSubnet.getIp4Prefix())
672 .build();
673
674 treatment = DefaultTrafficTreatment.builder()
675 .setTunnelId(Long.parseLong(dstSegmentId))
676 .transition(STAT_OUTBOUND_TABLE)
677 .build();
678
679 osFlowRuleService.setRule(
680 appId,
681 deviceId,
682 selector,
683 treatment,
684 PRIORITY_INTERNAL_ROUTING_RULE,
685 ROUTING_TABLE,
686 install);
687 }
688
689 private void setInternalRouterRulesForVlan(DeviceId deviceId,
690 String srcSegmentId,
691 String dstSegmentId,
692 IpPrefix srcSubnet,
693 IpPrefix dstSubnet,
694 boolean install) {
695 TrafficSelector selector;
696 TrafficTreatment treatment;
697 selector = DefaultTrafficSelector.builder()
698 .matchEthType(Ethernet.TYPE_IPV4)
699 .matchVlanId(VlanId.vlanId(srcSegmentId))
700 .matchIPSrc(srcSubnet.getIp4Prefix())
701 .matchIPDst(dstSubnet.getIp4Prefix())
702 .build();
703
704 treatment = DefaultTrafficTreatment.builder()
705 .setVlanId(VlanId.vlanId(dstSegmentId))
706 .transition(STAT_OUTBOUND_TABLE)
707 .build();
708
709 osFlowRuleService.setRule(
710 appId,
711 deviceId,
712 selector,
713 treatment,
714 PRIORITY_INTERNAL_ROUTING_RULE,
715 ROUTING_TABLE,
716 install);
717
718 selector = DefaultTrafficSelector.builder()
719 .matchEthType(Ethernet.TYPE_IPV4)
720 .matchVlanId(VlanId.vlanId(dstSegmentId))
721 .matchIPSrc(srcSubnet.getIp4Prefix())
722 .matchIPDst(dstSubnet.getIp4Prefix())
723 .build();
724
725 treatment = DefaultTrafficTreatment.builder()
726 .setVlanId(VlanId.vlanId(dstSegmentId))
727 .transition(STAT_OUTBOUND_TABLE)
728 .build();
729
730 osFlowRuleService.setRule(
731 appId,
732 deviceId,
733 selector,
734 treatment,
735 PRIORITY_INTERNAL_ROUTING_RULE,
736 ROUTING_TABLE,
737 install);
738 }
739
Jian Li5ecfd1a2018-12-10 11:41:03 +0900740 private void setRulesToGateway(OpenstackNode osNode,
741 String segmentId,
742 IpPrefix srcSubnet,
743 NetworkType networkType,
744 boolean install) {
745 OpenstackNode sourceNatGateway =
746 osNodeService.completeNodes(GATEWAY).stream().findFirst().orElse(null);
daniel parkb5817102018-02-15 00:18:51 +0900747
748 if (sourceNatGateway == null) {
749 return;
750 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900751
daniel parkee8700b2017-05-11 15:50:03 +0900752 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
753 .matchEthType(Ethernet.TYPE_IPV4)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900754 .matchIPSrc(srcSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900755 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
756
757 switch (networkType) {
758 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900759 case GRE:
daniel parkee8700b2017-05-11 15:50:03 +0900760 sBuilder.matchTunnelId(Long.parseLong(segmentId));
daniel parkee8700b2017-05-11 15:50:03 +0900761 break;
762 case VLAN:
763 sBuilder.matchVlanId(VlanId.vlanId(segmentId));
daniel parkee8700b2017-05-11 15:50:03 +0900764 break;
765 default:
Jian Li71670d12018-03-02 21:31:07 +0900766 final String error = String.format("%s %s",
767 ERR_UNSUPPORTED_NET_TYPE,
daniel parkee8700b2017-05-11 15:50:03 +0900768 networkType.toString());
769 throw new IllegalStateException(error);
770 }
771
Daniel Parkc64b4c62018-05-09 18:13:39 +0900772 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
773
774 switch (networkType) {
775 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900776 case GRE:
777 PortNumber portNum = tunnelPortNumByNetType(networkType.name(), osNode);
Daniel Parkc64b4c62018-05-09 18:13:39 +0900778 tBuilder.extension(buildExtension(
779 deviceService,
780 osNode.intgBridge(),
781 sourceNatGateway.dataIp().getIp4Address()),
782 osNode.intgBridge())
Jian Li2d68c192018-12-13 15:52:59 +0900783 .setOutput(portNum);
Daniel Parkc64b4c62018-05-09 18:13:39 +0900784 break;
785
786 case VLAN:
787 tBuilder.setOutput(osNode.vlanPortNum());
788 break;
789
790 default:
791 break;
792 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900793
sanghodc375372017-06-08 10:41:30 +0900794 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900795 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900796 osNode.intgBridge(),
daniel parkee8700b2017-05-11 15:50:03 +0900797 sBuilder.build(),
Daniel Parkc64b4c62018-05-09 18:13:39 +0900798 tBuilder.build(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900799 PRIORITY_EXTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900800 ROUTING_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900801 install);
802 }
803
Jian Li5ecfd1a2018-12-10 11:41:03 +0900804 private void setRulesForSnatIngressRule(DeviceId deviceId,
805 Long vni,
806 IpPrefix destVmIp,
807 DeviceId dstDeviceId,
Jian Li2d68c192018-12-13 15:52:59 +0900808 NetworkType networkType,
Jian Li5ecfd1a2018-12-10 11:41:03 +0900809 boolean install) {
sangho072c4dd2017-05-17 10:45:21 +0900810
811 TrafficSelector selector = DefaultTrafficSelector.builder()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900812 .matchEthType(Ethernet.TYPE_IPV4)
sangho072c4dd2017-05-17 10:45:21 +0900813 .matchIPDst(destVmIp)
814 .build();
Hyunsun Moon0d457362017-06-27 17:19:41 +0900815
Jian Li2d68c192018-12-13 15:52:59 +0900816 PortNumber portNum = tunnelPortNumByNetType(networkType.name(),
817 osNodeService.node(deviceId));
818
sangho072c4dd2017-05-17 10:45:21 +0900819 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
820 .setTunnelId(vni)
821 .extension(buildExtension(
822 deviceService,
823 deviceId,
824 osNodeService.node(dstDeviceId).dataIp().getIp4Address()),
825 deviceId)
Jian Li2d68c192018-12-13 15:52:59 +0900826 .setOutput(portNum)
sangho072c4dd2017-05-17 10:45:21 +0900827 .build();
daniel parkee8700b2017-05-11 15:50:03 +0900828
sanghodc375372017-06-08 10:41:30 +0900829 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900830 appId,
sangho072c4dd2017-05-17 10:45:21 +0900831 deviceId,
832 selector,
833 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900834 PRIORITY_EXTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900835 Constants.GW_COMMON_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900836 install);
837 }
838
Jian Li5ecfd1a2018-12-10 11:41:03 +0900839 private void setRulesToGatewayWithRoutableSubnets(OpenstackNode osNode,
840 OpenstackNode sourceNatGateway,
841 String segmentId,
842 Subnet updatedSubnet,
843 Set<Subnet> routableSubnets,
Jian Li2d68c192018-12-13 15:52:59 +0900844 NetworkType networkType,
Daniel Park51f9d1e2018-10-26 13:39:09 +0900845 boolean install) {
846 //At first we install flow rules to gateway with segId and gatewayIp of updated subnet
Jian Li5ecfd1a2018-12-10 11:41:03 +0900847 setRulesToGatewayWithDstIp(osNode, sourceNatGateway, segmentId,
Jian Li2d68c192018-12-13 15:52:59 +0900848 IpAddress.valueOf(updatedSubnet.getGateway()), networkType, install);
Daniel Park51f9d1e2018-10-26 13:39:09 +0900849
850 routableSubnets.forEach(subnet -> {
851 setRulesToGatewayWithDstIp(osNode, sourceNatGateway,
852 segmentId, IpAddress.valueOf(subnet.getGateway()),
Jian Li2d68c192018-12-13 15:52:59 +0900853 networkType, install);
Daniel Park51f9d1e2018-10-26 13:39:09 +0900854
855 Network network = osNetworkAdminService.network(subnet.getNetworkId());
856 setRulesToGatewayWithDstIp(osNode, sourceNatGateway,
857 network.getProviderSegID(), IpAddress.valueOf(updatedSubnet.getGateway()),
Jian Li2d68c192018-12-13 15:52:59 +0900858 networkType, install);
Daniel Park51f9d1e2018-10-26 13:39:09 +0900859 });
860 }
861
Jian Li5ecfd1a2018-12-10 11:41:03 +0900862 private void setRulesToGatewayWithDstIp(OpenstackNode osNode,
863 OpenstackNode sourceNatGateway,
864 String segmentId,
865 IpAddress dstIp,
Jian Li2d68c192018-12-13 15:52:59 +0900866 NetworkType networkType,
Jian Li5ecfd1a2018-12-10 11:41:03 +0900867 boolean install) {
Daniel Parkc64b4c62018-05-09 18:13:39 +0900868 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
869 .matchEthType(Ethernet.TYPE_IPV4)
870 .matchIPDst(dstIp.getIp4Address().toIpPrefix());
871
Daniel Parkc64b4c62018-05-09 18:13:39 +0900872 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
873
Jian Li2d68c192018-12-13 15:52:59 +0900874 switch (networkType) {
Daniel Parkc64b4c62018-05-09 18:13:39 +0900875 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900876 case GRE:
Daniel Park51f9d1e2018-10-26 13:39:09 +0900877 sBuilder.matchTunnelId(Long.parseLong(segmentId));
Jian Li2d68c192018-12-13 15:52:59 +0900878
879 PortNumber portNum = tunnelPortNumByNetType(networkType.name(), osNode);
880
Daniel Parkc64b4c62018-05-09 18:13:39 +0900881 tBuilder.extension(buildExtension(
daniel parkb5817102018-02-15 00:18:51 +0900882 deviceService,
883 osNode.intgBridge(),
884 sourceNatGateway.dataIp().getIp4Address()),
885 osNode.intgBridge())
Jian Li2d68c192018-12-13 15:52:59 +0900886 .setOutput(portNum);
Daniel Parkc64b4c62018-05-09 18:13:39 +0900887 break;
Daniel Parkc64b4c62018-05-09 18:13:39 +0900888 case VLAN:
Daniel Park51f9d1e2018-10-26 13:39:09 +0900889 sBuilder.matchVlanId(VlanId.vlanId(segmentId));
Daniel Parkc64b4c62018-05-09 18:13:39 +0900890 tBuilder.setOutput(osNode.vlanPortNum());
891 break;
892
893 default:
894 break;
895 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900896
sanghodc375372017-06-08 10:41:30 +0900897 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900898 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900899 osNode.intgBridge(),
Daniel Parkc64b4c62018-05-09 18:13:39 +0900900 sBuilder.build(),
901 tBuilder.build(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900902 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900903 ROUTING_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900904 install);
905 }
906
Jian Li5ecfd1a2018-12-10 11:41:03 +0900907 private void setOvsNatIngressRule(DeviceId deviceId,
908 IpPrefix cidr,
909 MacAddress dstMac,
910 boolean install) {
sangho072c4dd2017-05-17 10:45:21 +0900911
912 TrafficSelector selector = DefaultTrafficSelector.builder()
913 .matchEthType(Ethernet.TYPE_IPV4)
914 .matchIPDst(cidr)
915 .build();
916
Jian Liedc8b762018-03-22 15:42:00 +0900917 ExtensionTreatment natTreatment = RulePopulatorUtil
918 .niciraConnTrackTreatmentBuilder(driverService, deviceId)
sangho072c4dd2017-05-17 10:45:21 +0900919 .commit(false)
920 .natAction(true)
921 .table((short) 0)
922 .build();
923
924 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
925 .setEthDst(dstMac)
926 .extension(natTreatment, deviceId)
927 .build();
928
929 osFlowRuleService.setRule(
930 appId,
931 deviceId,
932 selector,
933 treatment,
sanghoe765ce22017-06-23 17:54:57 +0900934 PRIORITY_STATEFUL_SNAT_RULE,
sangho072c4dd2017-05-17 10:45:21 +0900935 GW_COMMON_TABLE,
936 install);
937 }
938
Jian Li5ecfd1a2018-12-10 11:41:03 +0900939 private void setOvsNatEgressRule(DeviceId deviceId,
940 IpAddress natAddress,
941 long vni,
942 PortNumber output,
sangho072c4dd2017-05-17 10:45:21 +0900943 boolean install) {
944
945 TrafficSelector selector = DefaultTrafficSelector.builder()
946 .matchEthType(Ethernet.TYPE_IPV4)
947 .matchEthDst(DEFAULT_GATEWAY_MAC)
948 .matchTunnelId(vni)
949 .build();
950
Jian Liedc8b762018-03-22 15:42:00 +0900951 ExtensionTreatment natTreatment = RulePopulatorUtil
952 .niciraConnTrackTreatmentBuilder(driverService, deviceId)
sangho072c4dd2017-05-17 10:45:21 +0900953 .commit(true)
954 .natAction(true)
955 .natIp(natAddress)
956 .build();
957
958 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
959 .extension(natTreatment, deviceId)
960 .setEthDst(DEFAULT_EXTERNAL_ROUTER_MAC)
961 .setEthSrc(DEFAULT_GATEWAY_MAC)
962 .setOutput(output)
963 .build();
964
965 osFlowRuleService.setRule(
966 appId,
967 deviceId,
968 selector,
969 treatment,
sanghoe765ce22017-06-23 17:54:57 +0900970 PRIORITY_STATEFUL_SNAT_RULE,
sangho072c4dd2017-05-17 10:45:21 +0900971 GW_COMMON_TABLE,
972 install);
973 }
974
Jian Li5ecfd1a2018-12-10 11:41:03 +0900975 private void setRulesToController(DeviceId deviceId,
976 String segmentId,
977 IpPrefix srcSubnet,
978 NetworkType networkType,
979 boolean install) {
sanghoe765ce22017-06-23 17:54:57 +0900980 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
981 .matchEthType(Ethernet.TYPE_IPV4)
Daniel Parkc64b4c62018-05-09 18:13:39 +0900982 .matchIPSrc(srcSubnet)
983 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
984
sanghoe765ce22017-06-23 17:54:57 +0900985 switch (networkType) {
986 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900987 case GRE:
Daniel Parkc64b4c62018-05-09 18:13:39 +0900988 sBuilder.matchTunnelId(Long.parseLong(segmentId));
sanghoe765ce22017-06-23 17:54:57 +0900989 break;
990 case VLAN:
Daniel Parkc64b4c62018-05-09 18:13:39 +0900991 sBuilder.matchVlanId(VlanId.vlanId(segmentId));
sanghoe765ce22017-06-23 17:54:57 +0900992 break;
993 default:
Jian Li71670d12018-03-02 21:31:07 +0900994 final String error = String.format("%s %s",
995 ERR_UNSUPPORTED_NET_TYPE,
sanghoe765ce22017-06-23 17:54:57 +0900996 networkType.toString());
997 throw new IllegalStateException(error);
998 }
999
Daniel Parkc64b4c62018-05-09 18:13:39 +09001000 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
sanghoe765ce22017-06-23 17:54:57 +09001001
1002 if (networkType.equals(NetworkType.VLAN)) {
1003 tBuilder.popVlan();
1004 }
1005
Jian Li4d5c5c32018-04-02 16:38:18 +09001006 tBuilder.punt();
sanghoe765ce22017-06-23 17:54:57 +09001007
1008 osFlowRuleService.setRule(
1009 appId,
1010 deviceId,
1011 sBuilder.build(),
1012 tBuilder.build(),
1013 PRIORITY_EXTERNAL_ROUTING_RULE,
1014 GW_COMMON_TABLE,
1015 install);
sanghoe765ce22017-06-23 17:54:57 +09001016 }
sangho072c4dd2017-05-17 10:45:21 +09001017
Jian Li5ecfd1a2018-12-10 11:41:03 +09001018 private void setRouterAdminRules(String segmentId,
1019 NetworkType networkType,
1020 boolean install) {
Frank Wang245a6822017-06-14 09:51:35 +08001021 TrafficTreatment treatment;
1022 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
1023 .matchEthType(Ethernet.TYPE_IPV4);
1024
1025 switch (networkType) {
1026 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +09001027 case GRE:
Frank Wang245a6822017-06-14 09:51:35 +08001028 sBuilder.matchTunnelId(Long.parseLong(segmentId));
1029 break;
1030 case VLAN:
1031 sBuilder.matchVlanId(VlanId.vlanId(segmentId));
1032 break;
1033 default:
Jian Li71670d12018-03-02 21:31:07 +09001034 final String error = String.format("%s %s",
1035 ERR_UNSUPPORTED_NET_TYPE,
Frank Wang245a6822017-06-14 09:51:35 +08001036 networkType.toString());
1037 throw new IllegalStateException(error);
1038 }
1039
1040 treatment = DefaultTrafficTreatment.builder()
1041 .drop()
1042 .build();
1043
1044 osNodeService.completeNodes().stream()
1045 .filter(osNode -> osNode.type() == COMPUTE)
1046 .forEach(osNode -> {
1047 osFlowRuleService.setRule(
1048 appId,
1049 osNode.intgBridge(),
1050 sBuilder.build(),
1051 treatment,
1052 PRIORITY_ADMIN_RULE,
1053 ROUTING_TABLE,
1054 install);
1055 });
1056 }
1057
Hyunsun Moon44aac662017-02-18 02:07:01 +09001058 private class InternalRouterEventListener implements OpenstackRouterListener {
1059
Jian Li34220ea2018-11-14 01:30:24 +09001060 private boolean isRelevantHelper() {
1061 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001062 }
1063
1064 // FIXME only one leader in the cluster should process
1065 @Override
1066 public void event(OpenstackRouterEvent event) {
1067 switch (event.type()) {
1068 case OPENSTACK_ROUTER_CREATED:
Jian Li4d138702018-11-27 17:25:28 +09001069 eventExecutor.execute(() -> processRouterCreation(event));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001070 break;
1071 case OPENSTACK_ROUTER_UPDATED:
Jian Li4d138702018-11-27 17:25:28 +09001072 eventExecutor.execute(() -> processRouterUpdate(event));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001073 break;
1074 case OPENSTACK_ROUTER_REMOVED:
Jian Li4d138702018-11-27 17:25:28 +09001075 eventExecutor.execute(() -> processRouterRemoval(event));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001076 break;
1077 case OPENSTACK_ROUTER_INTERFACE_ADDED:
Jian Li4d138702018-11-27 17:25:28 +09001078 eventExecutor.execute(() -> processRouterIntfCreation(event));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001079 break;
1080 case OPENSTACK_ROUTER_INTERFACE_UPDATED:
Jian Li4d138702018-11-27 17:25:28 +09001081 eventExecutor.execute(() -> processRouterIntfUpdate(event));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001082 break;
1083 case OPENSTACK_ROUTER_INTERFACE_REMOVED:
Jian Li4d138702018-11-27 17:25:28 +09001084 eventExecutor.execute(() -> processRouterIntfRemoval(event));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001085 break;
1086 case OPENSTACK_ROUTER_GATEWAY_ADDED:
Jian Li32b03622018-11-06 17:54:24 +09001087 log.debug("Router external gateway {} added",
1088 event.externalGateway().getNetworkId());
Ray Milkey08932a72018-02-20 15:34:38 -08001089 break;
Hyunsun Moon44aac662017-02-18 02:07:01 +09001090 case OPENSTACK_ROUTER_GATEWAY_REMOVED:
Jian Li32b03622018-11-06 17:54:24 +09001091 log.debug("Router external gateway {} removed",
1092 event.externalGateway().getNetworkId());
Ray Milkey08932a72018-02-20 15:34:38 -08001093 break;
Hyunsun Moon44aac662017-02-18 02:07:01 +09001094 case OPENSTACK_FLOATING_IP_CREATED:
1095 case OPENSTACK_FLOATING_IP_UPDATED:
1096 case OPENSTACK_FLOATING_IP_REMOVED:
1097 case OPENSTACK_FLOATING_IP_ASSOCIATED:
1098 case OPENSTACK_FLOATING_IP_DISASSOCIATED:
1099 default:
1100 // do nothing for the other events
1101 break;
1102 }
1103 }
Jian Li4d138702018-11-27 17:25:28 +09001104
1105 private void processRouterCreation(OpenstackRouterEvent event) {
1106 if (!isRelevantHelper()) {
1107 return;
1108 }
1109
1110 log.debug("Router(name:{}, ID:{}) is created",
1111 event.subject().getName(),
1112 event.subject().getId());
1113
1114 routerUpdated(event.subject());
1115 }
1116
1117 private void processRouterUpdate(OpenstackRouterEvent event) {
1118 if (!isRelevantHelper()) {
1119 return;
1120 }
1121
1122 log.debug("Router(name:{}, ID:{}) is updated",
1123 event.subject().getName(),
1124 event.subject().getId());
1125
1126 routerUpdated(event.subject());
1127 }
1128
1129 private void processRouterRemoval(OpenstackRouterEvent event) {
1130 if (!isRelevantHelper()) {
1131 return;
1132 }
1133
1134 log.debug("Router(name:{}, ID:{}) is removed",
1135 event.subject().getName(),
1136 event.subject().getId());
1137
1138 routerRemove(event.subject());
1139 }
1140
1141 private void processRouterIntfCreation(OpenstackRouterEvent event) {
1142 if (!isRelevantHelper()) {
1143 return;
1144 }
1145
1146 log.debug("Router interface {} added to router {}",
1147 event.routerIface().getPortId(),
1148 event.routerIface().getId());
1149
1150 routerIfaceAdded(event.subject(), event.routerIface());
1151 }
1152
1153 private void processRouterIntfUpdate(OpenstackRouterEvent event) {
1154 log.debug("Router interface {} on {} updated",
1155 event.routerIface().getPortId(),
1156 event.routerIface().getId());
1157 }
1158
1159 private void processRouterIntfRemoval(OpenstackRouterEvent event) {
1160 if (!isRelevantHelper()) {
1161 return;
1162 }
1163
1164 log.debug("Router interface {} removed from router {}",
1165 event.routerIface().getPortId(),
1166 event.routerIface().getId());
1167
1168 routerIfaceRemoved(event.subject(), event.routerIface());
1169 }
Hyunsun Moon44aac662017-02-18 02:07:01 +09001170 }
1171
1172 private class InternalNodeEventListener implements OpenstackNodeListener {
1173
Jian Li34220ea2018-11-14 01:30:24 +09001174 private boolean isRelevantHelper() {
1175 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001176 }
1177
1178 @Override
1179 public void event(OpenstackNodeEvent event) {
1180 OpenstackNode osNode = event.subject();
Hyunsun Moon44aac662017-02-18 02:07:01 +09001181 switch (event.type()) {
Hyunsun Moon0d457362017-06-27 17:19:41 +09001182 case OPENSTACK_NODE_COMPLETE:
1183 case OPENSTACK_NODE_INCOMPLETE:
Daniel Park6ed9cf02018-06-27 19:07:44 +09001184 case OPENSTACK_NODE_UPDATED:
1185 case OPENSTACK_NODE_REMOVED:
Hyunsun Moon44aac662017-02-18 02:07:01 +09001186 eventExecutor.execute(() -> {
Jian Li34220ea2018-11-14 01:30:24 +09001187 if (!isRelevantHelper()) {
1188 return;
1189 }
Jian Li4d138702018-11-27 17:25:28 +09001190 reconfigureRouters(osNode);
Hyunsun Moon44aac662017-02-18 02:07:01 +09001191 });
1192 break;
Hyunsun Moon0d457362017-06-27 17:19:41 +09001193 case OPENSTACK_NODE_CREATED:
Hyunsun Moon44aac662017-02-18 02:07:01 +09001194 default:
1195 break;
1196 }
1197 }
1198
Jian Li4d138702018-11-27 17:25:28 +09001199 private void reconfigureRouters(OpenstackNode osNode) {
Hyunsun Moon44aac662017-02-18 02:07:01 +09001200 osRouterService.routers().forEach(osRouter -> {
1201 routerUpdated(osRouter);
1202 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
1203 routerIfaceAdded(osRouter, iface);
1204 });
1205 });
Jian Li4d138702018-11-27 17:25:28 +09001206 log.info("Reconfigure routers for {}", osNode.hostname());
Hyunsun Moon44aac662017-02-18 02:07:01 +09001207 }
1208 }
sangho072c4dd2017-05-17 10:45:21 +09001209
1210 private class InternalInstancePortListener implements InstancePortListener {
1211
Jian Li34220ea2018-11-14 01:30:24 +09001212 private boolean isRelevantHelper(InstancePortEvent event) {
1213 return mastershipService.isLocalMaster(event.subject().deviceId());
sangho072c4dd2017-05-17 10:45:21 +09001214 }
1215
1216 @Override
1217 public void event(InstancePortEvent event) {
1218 InstancePort instPort = event.subject();
1219 switch (event.type()) {
sangho072c4dd2017-05-17 10:45:21 +09001220 case OPENSTACK_INSTANCE_PORT_DETECTED:
Jian Liec5c32b2018-07-13 14:28:58 +09001221 case OPENSTACK_INSTANCE_PORT_UPDATED:
Jian Li4d138702018-11-27 17:25:28 +09001222 eventExecutor.execute(() ->
1223 processInstancePortDetection(event, instPort));
sangho072c4dd2017-05-17 10:45:21 +09001224 break;
1225 case OPENSTACK_INSTANCE_PORT_VANISHED:
Jian Li4d138702018-11-27 17:25:28 +09001226 eventExecutor.execute(() ->
1227 processInstancePortRemoval(event, instPort));
Jian Liec5c32b2018-07-13 14:28:58 +09001228 break;
1229 case OPENSTACK_INSTANCE_MIGRATION_STARTED:
Jian Li4d138702018-11-27 17:25:28 +09001230 eventExecutor.execute(() ->
1231 processInstanceMigrationStart(event, instPort));
sangho072c4dd2017-05-17 10:45:21 +09001232 break;
Jian Li24ec59f2018-05-23 19:01:25 +09001233 case OPENSTACK_INSTANCE_MIGRATION_ENDED:
Jian Li4d138702018-11-27 17:25:28 +09001234 eventExecutor.execute(() ->
1235 processInstanceMigrationEnd(event, instPort));
Jian Li24ec59f2018-05-23 19:01:25 +09001236 break;
sangho072c4dd2017-05-17 10:45:21 +09001237 default:
1238 break;
1239 }
1240 }
1241
Jian Li4d138702018-11-27 17:25:28 +09001242 private void processInstancePortDetection(InstancePortEvent event,
1243 InstancePort instPort) {
1244 if (!isRelevantHelper(event)) {
1245 return;
1246 }
1247
1248 log.info("RoutingHandler: Instance port detected MAC:{} IP:{}",
1249 instPort.macAddress(),
1250 instPort.ipAddress());
1251
1252 instPortDetected(event.subject());
1253 }
1254
1255 private void processInstancePortRemoval(InstancePortEvent event,
1256 InstancePort instPort) {
1257 if (!isRelevantHelper(event)) {
1258 return;
1259 }
1260
1261 log.info("RoutingHandler: Instance port vanished MAC:{} IP:{}",
1262 instPort.macAddress(),
1263 instPort.ipAddress());
1264
1265 instPortRemoved(event.subject());
1266 }
1267
1268 private void processInstanceMigrationStart(InstancePortEvent event,
1269 InstancePort instPort) {
1270 if (!isRelevantHelper(event)) {
1271 return;
1272 }
1273
1274 log.info("RoutingHandler: Migration started for MAC:{} IP:{}",
1275 instPort.macAddress(),
1276 instPort.ipAddress());
1277
1278 instPortDetected(instPort);
1279 }
1280
1281 private void processInstanceMigrationEnd(InstancePortEvent event,
1282 InstancePort instPort) {
1283 log.info("RoutingHandler: Migration finished for MAC:{} IP:{}",
1284 instPort.macAddress(),
1285 instPort.ipAddress());
1286 // TODO: need to reconfigure rules to point to update VM
1287 }
1288
sangho072c4dd2017-05-17 10:45:21 +09001289 private void instPortDetected(InstancePort instPort) {
Jian Li4d138702018-11-27 17:25:28 +09001290 Network network = osNetworkAdminService.network(instPort.networkId());
1291 if (network.getNetworkType() == FLAT) {
daniel park796c2eb2018-03-22 17:01:51 +09001292 return;
1293 }
Daniel Parkc64b4c62018-05-09 18:13:39 +09001294
1295 if (useStatefulSnat) {
1296 osNodeService.completeNodes(GATEWAY)
1297 .forEach(gwNode -> setRulesForSnatIngressRule(
1298 gwNode.intgBridge(),
Jian Li4d138702018-11-27 17:25:28 +09001299 Long.parseLong(network.getProviderSegID()),
1300 IpPrefix.valueOf(instPort.ipAddress(), VM_PREFIX),
Jian Li2d68c192018-12-13 15:52:59 +09001301 instPort.deviceId(), network.getNetworkType(), true));
Daniel Parkc64b4c62018-05-09 18:13:39 +09001302 }
sangho072c4dd2017-05-17 10:45:21 +09001303 }
1304
1305 private void instPortRemoved(InstancePort instPort) {
Jian Li4d138702018-11-27 17:25:28 +09001306 Network network = osNetworkAdminService.network(instPort.networkId());
1307 if (network.getNetworkType() == FLAT) {
daniel park796c2eb2018-03-22 17:01:51 +09001308 return;
1309 }
Daniel Parkc64b4c62018-05-09 18:13:39 +09001310
1311 if (useStatefulSnat) {
1312 osNodeService.completeNodes(GATEWAY)
1313 .forEach(gwNode -> setRulesForSnatIngressRule(
1314 gwNode.intgBridge(),
Jian Li4d138702018-11-27 17:25:28 +09001315 Long.parseLong(network.getProviderSegID()),
1316 IpPrefix.valueOf(instPort.ipAddress(), VM_PREFIX),
Jian Li2d68c192018-12-13 15:52:59 +09001317 instPort.deviceId(), network.getNetworkType(), false));
Daniel Parkc64b4c62018-05-09 18:13:39 +09001318 }
sangho072c4dd2017-05-17 10:45:21 +09001319 }
1320 }
Hyunsun Moon44aac662017-02-18 02:07:01 +09001321}