blob: d1864d79d2822ab5ea0d859b852469230db22c66 [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;
SONA Project6bc5c4a2018-12-14 23:49:52 +090051import org.onosproject.openstacknetworking.api.OpenstackNetwork.Type;
daniel park32b42202018-03-14 16:53:44 +090052import org.onosproject.openstacknetworking.api.OpenstackNetworkAdminService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090053import org.onosproject.openstacknetworking.api.OpenstackRouterEvent;
54import org.onosproject.openstacknetworking.api.OpenstackRouterListener;
55import org.onosproject.openstacknetworking.api.OpenstackRouterService;
Jian Li26949762018-03-30 15:46:37 +090056import org.onosproject.openstacknetworking.util.RulePopulatorUtil;
Hyunsun Moon0d457362017-06-27 17:19:41 +090057import org.onosproject.openstacknode.api.OpenstackNode;
Hyunsun Moon0d457362017-06-27 17:19:41 +090058import org.onosproject.openstacknode.api.OpenstackNodeEvent;
59import org.onosproject.openstacknode.api.OpenstackNodeListener;
60import org.onosproject.openstacknode.api.OpenstackNodeService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090061import org.openstack4j.model.network.ExternalGateway;
62import org.openstack4j.model.network.Network;
63import 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;
SONA Project6bc5c4a2018-12-14 23:49:52 +090098import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.FLAT;
Jian Li621f73c2018-12-15 01:49:22 +090099import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.GENEVE;
100import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.GRE;
SONA Project6bc5c4a2018-12-14 23:49:52 +0900101import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.VLAN;
Jian Li621f73c2018-12-15 01:49:22 +0900102import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.VXLAN;
Ray Milkey8e406512018-10-24 15:56:50 -0700103import static org.onosproject.openstacknetworking.impl.OsgiPropertyConstants.USE_STATEFUL_SNAT;
104import static org.onosproject.openstacknetworking.impl.OsgiPropertyConstants.USE_STATEFUL_SNAT_DEFAULT;
Jian Li2d68c192018-12-13 15:52:59 +0900105import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.tunnelPortNumByNetType;
Jian Li26949762018-03-30 15:46:37 +0900106import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900107import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
108import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900109
110/**
111 * Handles OpenStack router events.
112 */
Ray Milkey8e406512018-10-24 15:56:50 -0700113@Component(
114 immediate = true,
115 property = {
116 USE_STATEFUL_SNAT + ":Boolean=" + USE_STATEFUL_SNAT_DEFAULT
117 }
118)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900119public class OpenstackRoutingHandler {
120
121 private final Logger log = LoggerFactory.getLogger(getClass());
122
123 private static final String MSG_ENABLED = "Enabled ";
124 private static final String MSG_DISABLED = "Disabled ";
daniel parkee8700b2017-05-11 15:50:03 +0900125 private static final String ERR_UNSUPPORTED_NET_TYPE = "Unsupported network type";
sanghoe765ce22017-06-23 17:54:57 +0900126
Jian Li4d138702018-11-27 17:25:28 +0900127 private static final int VM_PREFIX = 32;
128
Ray Milkey8e406512018-10-24 15:56:50 -0700129 /** Use Stateful SNAT for source NATing. */
130 private boolean useStatefulSnat = USE_STATEFUL_SNAT_DEFAULT;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900131
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700132 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900133 protected CoreService coreService;
134
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700135 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900136 protected LeadershipService leadershipService;
137
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700138 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900139 protected ClusterService clusterService;
140
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700141 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900142 protected OpenstackNodeService osNodeService;
143
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700144 @Reference(cardinality = ReferenceCardinality.MANDATORY)
daniel park32b42202018-03-14 16:53:44 +0900145 protected OpenstackNetworkAdminService osNetworkAdminService;
146
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700147 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900148 protected OpenstackRouterService osRouterService;
149
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700150 @Reference(cardinality = ReferenceCardinality.MANDATORY)
sangho072c4dd2017-05-17 10:45:21 +0900151 protected InstancePortService instancePortService;
152
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700153 @Reference(cardinality = ReferenceCardinality.MANDATORY)
sangho072c4dd2017-05-17 10:45:21 +0900154 protected DeviceService deviceService;
155
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700156 @Reference(cardinality = ReferenceCardinality.MANDATORY)
sanghodc375372017-06-08 10:41:30 +0900157 protected OpenstackFlowRuleService osFlowRuleService;
158
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700159 @Reference(cardinality = ReferenceCardinality.MANDATORY)
sangho072c4dd2017-05-17 10:45:21 +0900160 protected MastershipService mastershipService;
161
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700162 @Reference(cardinality = ReferenceCardinality.MANDATORY)
sangho072c4dd2017-05-17 10:45:21 +0900163 protected DriverService driverService;
164
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700165 @Reference(cardinality = ReferenceCardinality.MANDATORY)
sanghoe765ce22017-06-23 17:54:57 +0900166 protected ComponentConfigService configService;
167
Hyunsun Moon44aac662017-02-18 02:07:01 +0900168 private final ExecutorService eventExecutor = newSingleThreadScheduledExecutor(
169 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
170 private final OpenstackNodeListener osNodeListener = new InternalNodeEventListener();
171 private final OpenstackRouterListener osRouterListener = new InternalRouterEventListener();
sangho072c4dd2017-05-17 10:45:21 +0900172 private final InstancePortListener instancePortListener = new InternalInstancePortListener();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900173
174 private ApplicationId appId;
175 private NodeId localNodeId;
176
177 @Activate
178 protected void activate() {
179 appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
180 localNodeId = clusterService.getLocalNode().id();
181 leadershipService.runForLeadership(appId.name());
182 osNodeService.addListener(osNodeListener);
183 osRouterService.addListener(osRouterListener);
sangho072c4dd2017-05-17 10:45:21 +0900184 instancePortService.addListener(instancePortListener);
sanghoe765ce22017-06-23 17:54:57 +0900185 configService.registerProperties(getClass());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900186
187 log.info("Started");
188 }
189
190 @Deactivate
191 protected void deactivate() {
192 osRouterService.removeListener(osRouterListener);
193 osNodeService.removeListener(osNodeListener);
sangho072c4dd2017-05-17 10:45:21 +0900194 instancePortService.removeListener(instancePortListener);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900195 leadershipService.withdraw(appId.name());
sanghoe765ce22017-06-23 17:54:57 +0900196 configService.unregisterProperties(getClass(), false);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900197 eventExecutor.shutdown();
198
199 log.info("Stopped");
200 }
201
sanghoe765ce22017-06-23 17:54:57 +0900202 @Modified
203 protected void modified(ComponentContext context) {
204 Dictionary<?, ?> properties = context.getProperties();
205 Boolean flag;
206
Ray Milkey8e406512018-10-24 15:56:50 -0700207 flag = Tools.isPropertyEnabled(properties, USE_STATEFUL_SNAT);
sanghoe765ce22017-06-23 17:54:57 +0900208 if (flag == null) {
209 log.info("useStatefulSnat is not configured, " +
210 "using current value of {}", useStatefulSnat);
211 } else {
212 useStatefulSnat = flag;
213 log.info("Configured. useStatefulSnat is {}",
214 useStatefulSnat ? "enabled" : "disabled");
215 }
216
217 resetSnatRules();
218 }
219
Hyunsun Moon44aac662017-02-18 02:07:01 +0900220 private void routerUpdated(Router osRouter) {
221 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
Frank Wang245a6822017-06-14 09:51:35 +0800222 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
Jian Li5ecfd1a2018-12-10 11:41:03 +0900223 Network network = osNetworkAdminService.network(
224 osNetworkAdminService.subnet(iface.getSubnetId())
Frank Wang245a6822017-06-14 09:51:35 +0800225 .getNetworkId());
SONA Project6bc5c4a2018-12-14 23:49:52 +0900226 Type netType = osNetworkAdminService.networkType(
227 osNetworkAdminService.subnet(iface.getSubnetId())
228 .getNetworkId());
Jian Li5ecfd1a2018-12-10 11:41:03 +0900229 setRouterAdminRules(network.getProviderSegID(),
SONA Project6bc5c4a2018-12-14 23:49:52 +0900230 netType, !osRouter.isAdminStateUp());
Frank Wang245a6822017-06-14 09:51:35 +0800231 });
232
Jian Li5ecfd1a2018-12-10 11:41:03 +0900233 ExternalPeerRouter externalPeerRouter =
234 osNetworkAdminService.externalPeerRouter(exGateway);
Jian Li5e2ad4a2018-07-16 13:40:53 +0900235 VlanId vlanId = externalPeerRouter == null ? VlanId.NONE : externalPeerRouter.vlanId();
daniel park576969a2018-03-09 07:07:41 +0900236
Hyunsun Moon44aac662017-02-18 02:07:01 +0900237 if (exGateway == null) {
Daniel Park613ac372018-06-28 14:30:11 +0900238 deleteUnassociatedExternalPeerRouter();
Jian Li5ecfd1a2018-12-10 11:41:03 +0900239 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface ->
240 setSourceNat(iface, false));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900241 } else {
daniel park32b42202018-03-14 16:53:44 +0900242 osNetworkAdminService.deriveExternalPeerRouterMac(exGateway, osRouter, vlanId);
daniel park576969a2018-03-09 07:07:41 +0900243 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface ->
244 setSourceNat(iface, exGateway.isEnableSnat()));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900245 }
246 }
247
Daniel Park613ac372018-06-28 14:30:11 +0900248 private void deleteUnassociatedExternalPeerRouter() {
249 log.trace("Deleting unassociated external peer router");
250
251 try {
252 Set<String> routerIps = Sets.newConcurrentHashSet();
253
254 osRouterService.routers().stream()
255 .filter(router -> getGatewayIpAddress(router) != null)
256 .map(router -> getGatewayIpAddress(router).toString())
257 .forEach(routerIps::add);
258
259 osNetworkAdminService.externalPeerRouters().stream()
260 .filter(externalPeerRouter ->
Jian Li5e2ad4a2018-07-16 13:40:53 +0900261 !routerIps.contains(externalPeerRouter.ipAddress().toString()))
Daniel Park613ac372018-06-28 14:30:11 +0900262 .forEach(externalPeerRouter -> {
263 osNetworkAdminService
Jian Li5ecfd1a2018-12-10 11:41:03 +0900264 .deleteExternalPeerRouter(
265 externalPeerRouter.ipAddress().toString());
Daniel Park613ac372018-06-28 14:30:11 +0900266 log.trace("Deleted unassociated external peer router {}",
Jian Li5e2ad4a2018-07-16 13:40:53 +0900267 externalPeerRouter.ipAddress().toString());
Daniel Park613ac372018-06-28 14:30:11 +0900268 });
269 } catch (Exception e) {
270 log.error("Exception occurred because of {}", e.toString());
271 }
272 }
273
Frank Wang245a6822017-06-14 09:51:35 +0800274 private void routerRemove(Router osRouter) {
275 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
Jian Li5ecfd1a2018-12-10 11:41:03 +0900276 Network network = osNetworkAdminService.network(
277 osNetworkAdminService.subnet(iface.getSubnetId())
Frank Wang245a6822017-06-14 09:51:35 +0800278 .getNetworkId());
SONA Project6bc5c4a2018-12-14 23:49:52 +0900279 Type netType = osNetworkAdminService.networkType(
280 osNetworkAdminService.subnet(iface.getSubnetId())
281 .getNetworkId());
282 setRouterAdminRules(network.getProviderSegID(), netType, false);
Frank Wang245a6822017-06-14 09:51:35 +0800283 });
284 }
285
Hyunsun Moon44aac662017-02-18 02:07:01 +0900286 private void routerIfaceAdded(Router osRouter, RouterInterface osRouterIface) {
Jian Liedc8b762018-03-22 15:42:00 +0900287 Subnet osSubnet = osNetworkAdminService.subnet(osRouterIface.getSubnetId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900288 if (osSubnet == null) {
289 final String error = String.format(
Jian Li71670d12018-03-02 21:31:07 +0900290 "Failed to set flows for router %s: subnet %s does not exist",
Hyunsun Moon44aac662017-02-18 02:07:01 +0900291 osRouterIface.getId(),
292 osRouterIface.getSubnetId());
293 throw new IllegalStateException(error);
294 }
Frank Wang245a6822017-06-14 09:51:35 +0800295
296 if (!osRouter.isAdminStateUp()) {
Jian Liedc8b762018-03-22 15:42:00 +0900297 Network network = osNetworkAdminService.network(osSubnet.getNetworkId());
SONA Project6bc5c4a2018-12-14 23:49:52 +0900298 Type netType = osNetworkAdminService.networkType(osSubnet.getNetworkId());
299 setRouterAdminRules(network.getProviderSegID(), netType, true);
Frank Wang245a6822017-06-14 09:51:35 +0800300 }
301
Hyunsun Moon44aac662017-02-18 02:07:01 +0900302 setInternalRoutes(osRouter, osSubnet, true);
Daniel Park51f9d1e2018-10-26 13:39:09 +0900303 setGatewayIcmp(osSubnet, osRouter, true);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900304 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
305 if (exGateway != null && exGateway.isEnableSnat()) {
daniel park576969a2018-03-09 07:07:41 +0900306 setSourceNat(osRouterIface, true);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900307 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900308 log.info("Connected subnet({}) to {}", osSubnet.getCidr(), osRouter.getName());
309 }
310
311 private void routerIfaceRemoved(Router osRouter, RouterInterface osRouterIface) {
Jian Liedc8b762018-03-22 15:42:00 +0900312 Subnet osSubnet = osNetworkAdminService.subnet(osRouterIface.getSubnetId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900313 if (osSubnet == null) {
314 final String error = String.format(
Jian Li71670d12018-03-02 21:31:07 +0900315 "Failed to set flows for router %s: subnet %s does not exist",
Hyunsun Moon44aac662017-02-18 02:07:01 +0900316 osRouterIface.getId(),
317 osRouterIface.getSubnetId());
318 throw new IllegalStateException(error);
319 }
320
Frank Wang245a6822017-06-14 09:51:35 +0800321 if (!osRouter.isAdminStateUp()) {
Jian Liedc8b762018-03-22 15:42:00 +0900322 Network network = osNetworkAdminService.network(osSubnet.getNetworkId());
SONA Project6bc5c4a2018-12-14 23:49:52 +0900323 Type netType = osNetworkAdminService.networkType(osSubnet.getNetworkId());
324 setRouterAdminRules(network.getProviderSegID(), netType, false);
Frank Wang245a6822017-06-14 09:51:35 +0800325 }
326
Hyunsun Moon44aac662017-02-18 02:07:01 +0900327 setInternalRoutes(osRouter, osSubnet, false);
Daniel Park51f9d1e2018-10-26 13:39:09 +0900328 setGatewayIcmp(osSubnet, osRouter, false);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900329 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
330 if (exGateway != null && exGateway.isEnableSnat()) {
daniel park576969a2018-03-09 07:07:41 +0900331 setSourceNat(osRouterIface, false);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900332 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900333 log.info("Disconnected subnet({}) from {}", osSubnet.getCidr(), osRouter.getName());
334 }
335
daniel park576969a2018-03-09 07:07:41 +0900336 private void setSourceNat(RouterInterface routerIface, boolean install) {
Jian Liedc8b762018-03-22 15:42:00 +0900337 Subnet osSubnet = osNetworkAdminService.subnet(routerIface.getSubnetId());
338 Network osNet = osNetworkAdminService.network(osSubnet.getNetworkId());
SONA Project6bc5c4a2018-12-14 23:49:52 +0900339 Type netType = osNetworkAdminService.networkType(osSubnet.getNetworkId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900340
Hyunsun Moon0d457362017-06-27 17:19:41 +0900341 osNodeService.completeNodes(COMPUTE).forEach(cNode -> {
342 setRulesToGateway(cNode, osNet.getProviderSegID(),
SONA Project6bc5c4a2018-12-14 23:49:52 +0900343 IpPrefix.valueOf(osSubnet.getCidr()), netType, install);
Hyunsun Moon0d457362017-06-27 17:19:41 +0900344 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900345
sanghoe765ce22017-06-23 17:54:57 +0900346 if (useStatefulSnat) {
347 setStatefulSnatRules(routerIface, install);
348 } else {
349 setReactiveSnatRules(routerIface, install);
350 }
351
352 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
353 log.info(updateStr + "external access for subnet({})", osSubnet.getCidr());
354 }
355
356 private void setStatefulSnatRules(RouterInterface routerIface, boolean install) {
Jian Liedc8b762018-03-22 15:42:00 +0900357 Subnet osSubnet = osNetworkAdminService.subnet(routerIface.getSubnetId());
358 Network osNet = osNetworkAdminService.network(osSubnet.getNetworkId());
SONA Project6bc5c4a2018-12-14 23:49:52 +0900359 Type netType = osNetworkAdminService.networkType(osSubnet.getNetworkId());
sanghoe765ce22017-06-23 17:54:57 +0900360
SONA Project6bc5c4a2018-12-14 23:49:52 +0900361 if (netType == FLAT) {
daniel park796c2eb2018-03-22 17:01:51 +0900362 return;
363 }
364
sanghoe765ce22017-06-23 17:54:57 +0900365 Optional<Router> osRouter = osRouterService.routers().stream()
366 .filter(router -> osRouterService.routerInterfaces(routerIface.getId()) != null)
367 .findAny();
368
369 if (!osRouter.isPresent()) {
370 log.error("Cannot find a router for router interface {} ", routerIface);
371 return;
372 }
373 IpAddress natAddress = getGatewayIpAddress(osRouter.get());
sangho072c4dd2017-05-17 10:45:21 +0900374 if (natAddress == null) {
375 return;
376 }
Jian Liedc8b762018-03-22 15:42:00 +0900377 String netId = osNetworkAdminService.subnet(routerIface.getSubnetId()).getNetworkId();
sangho072c4dd2017-05-17 10:45:21 +0900378
379 osNodeService.completeNodes(OpenstackNode.NodeType.GATEWAY)
380 .forEach(gwNode -> {
daniel park576969a2018-03-09 07:07:41 +0900381 instancePortService.instancePorts(netId)
Jian Lic2403592018-07-18 12:56:45 +0900382 .stream()
383 .filter(port -> port.state() == ACTIVE)
daniel park576969a2018-03-09 07:07:41 +0900384 .forEach(port -> setRulesForSnatIngressRule(gwNode.intgBridge(),
sangho072c4dd2017-05-17 10:45:21 +0900385 Long.parseLong(osNet.getProviderSegID()),
Jian Li4d138702018-11-27 17:25:28 +0900386 IpPrefix.valueOf(port.ipAddress(), VM_PREFIX),
sangho072c4dd2017-05-17 10:45:21 +0900387 port.deviceId(),
SONA Project6bc5c4a2018-12-14 23:49:52 +0900388 netType,
sangho072c4dd2017-05-17 10:45:21 +0900389 install));
390
391 setOvsNatIngressRule(gwNode.intgBridge(),
Jian Li4d138702018-11-27 17:25:28 +0900392 IpPrefix.valueOf(natAddress, VM_PREFIX),
sangho072c4dd2017-05-17 10:45:21 +0900393 Constants.DEFAULT_EXTERNAL_ROUTER_MAC, install);
394 setOvsNatEgressRule(gwNode.intgBridge(),
395 natAddress, Long.parseLong(osNet.getProviderSegID()),
396 gwNode.patchPortNum(), install);
397 });
sanghoe765ce22017-06-23 17:54:57 +0900398 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900399
sanghoe765ce22017-06-23 17:54:57 +0900400 private void setReactiveSnatRules(RouterInterface routerIface, boolean install) {
Jian Liedc8b762018-03-22 15:42:00 +0900401 Subnet osSubnet = osNetworkAdminService.subnet(routerIface.getSubnetId());
402 Network osNet = osNetworkAdminService.network(osSubnet.getNetworkId());
SONA Project6bc5c4a2018-12-14 23:49:52 +0900403 Type netType = osNetworkAdminService.networkType(osSubnet.getNetworkId());
sanghoe765ce22017-06-23 17:54:57 +0900404
405 osNodeService.completeNodes(GATEWAY)
406 .forEach(gwNode -> setRulesToController(
407 gwNode.intgBridge(),
408 osNet.getProviderSegID(),
409 IpPrefix.valueOf(osSubnet.getCidr()),
SONA Project6bc5c4a2018-12-14 23:49:52 +0900410 netType,
sanghoe765ce22017-06-23 17:54:57 +0900411 install));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900412 }
413
sangho072c4dd2017-05-17 10:45:21 +0900414 private IpAddress getGatewayIpAddress(Router osRouter) {
415
Daniel Park613ac372018-06-28 14:30:11 +0900416 if (osRouter.getExternalGatewayInfo() == null) {
417 return null;
418 }
Jian Li5ecfd1a2018-12-10 11:41:03 +0900419 String extNetId = osNetworkAdminService.network(
420 osRouter.getExternalGatewayInfo().getNetworkId()).getId();
Jian Liedc8b762018-03-22 15:42:00 +0900421 Optional<Subnet> extSubnet = osNetworkAdminService.subnets().stream()
sangho072c4dd2017-05-17 10:45:21 +0900422 .filter(subnet -> subnet.getNetworkId().equals(extNetId))
423 .findAny();
424
425 if (!extSubnet.isPresent()) {
426 log.error("Cannot find externel subnet for the router");
427 return null;
428 }
429
430 return IpAddress.valueOf(extSubnet.get().getGateway());
431 }
432
sanghoe765ce22017-06-23 17:54:57 +0900433 private void resetSnatRules() {
434 if (useStatefulSnat) {
435 osRouterService.routerInterfaces().forEach(
436 routerIface -> {
437 setReactiveSnatRules(routerIface, false);
438 setStatefulSnatRules(routerIface, true);
439 }
440 );
441 } else {
442 osRouterService.routerInterfaces().forEach(
443 routerIface -> {
444 setStatefulSnatRules(routerIface, false);
445 setReactiveSnatRules(routerIface, true);
446 }
447 );
448 }
449 }
450
Daniel Park51f9d1e2018-10-26 13:39:09 +0900451 private void setGatewayIcmp(Subnet osSubnet, Router osRouter, boolean install) {
Jian Li4d138702018-11-27 17:25:28 +0900452 OpenstackNode srcNatGw = osNodeService.completeNodes(GATEWAY)
453 .stream().findFirst().orElse(null);
daniel parkb5817102018-02-15 00:18:51 +0900454
Jian Li4d138702018-11-27 17:25:28 +0900455 if (srcNatGw == null) {
daniel parkb5817102018-02-15 00:18:51 +0900456 return;
457 }
458
Hyunsun Moon44aac662017-02-18 02:07:01 +0900459 if (Strings.isNullOrEmpty(osSubnet.getGateway())) {
460 // do nothing if no gateway is set
461 return;
462 }
463
464 // take ICMP request to a subnet gateway through gateway node group
Jian Li4d138702018-11-27 17:25:28 +0900465 Network net = osNetworkAdminService.network(osSubnet.getNetworkId());
Jian Li621f73c2018-12-15 01:49:22 +0900466 Type netType = osNetworkAdminService.networkType(osSubnet.getNetworkId());
Daniel Park51f9d1e2018-10-26 13:39:09 +0900467 Set<Subnet> routableSubnets = routableSubnets(osRouter, osSubnet.getId());
468
Jian Li621f73c2018-12-15 01:49:22 +0900469 switch (netType) {
daniel parkee8700b2017-05-11 15:50:03 +0900470 case VXLAN:
Jian Li4d138702018-11-27 17:25:28 +0900471 setGatewayIcmpForVxlan(osSubnet, srcNatGw, net, routableSubnets, install);
daniel parkee8700b2017-05-11 15:50:03 +0900472 break;
Jian Li2d68c192018-12-13 15:52:59 +0900473 case GRE:
474 setGatewayIcmpForGre(osSubnet, srcNatGw, net, routableSubnets, install);
475 break;
Jian Li621f73c2018-12-15 01:49:22 +0900476 case GENEVE:
477 setGatewayIcmpForGeneve(osSubnet, srcNatGw, net, routableSubnets, install);
478 break;
daniel parkee8700b2017-05-11 15:50:03 +0900479 case VLAN:
Jian Li4d138702018-11-27 17:25:28 +0900480 setGatewayIcmpForVlan(osSubnet, srcNatGw, net, routableSubnets, install);
daniel parkee8700b2017-05-11 15:50:03 +0900481 break;
482 default:
Jian Li4d138702018-11-27 17:25:28 +0900483 final String error = String.format("%s %s", ERR_UNSUPPORTED_NET_TYPE,
Jian Li621f73c2018-12-15 01:49:22 +0900484 netType.toString());
daniel parkee8700b2017-05-11 15:50:03 +0900485 throw new IllegalStateException(error);
486 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900487
488 IpAddress gatewayIp = IpAddress.valueOf(osSubnet.getGateway());
daniel park576969a2018-03-09 07:07:41 +0900489 osNodeService.completeNodes(GATEWAY).forEach(gNode ->
Hyunsun Moon0d457362017-06-27 17:19:41 +0900490 setGatewayIcmpRule(
491 gatewayIp,
492 gNode.intgBridge(),
daniel park576969a2018-03-09 07:07:41 +0900493 install));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900494
495 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
496 log.debug(updateStr + "ICMP to {}", osSubnet.getGateway());
497 }
498
Jian Li4d138702018-11-27 17:25:28 +0900499 private void setGatewayIcmpForVxlan(Subnet osSubnet,
500 OpenstackNode srcNatGw,
501 Network network,
502 Set<Subnet> routableSubnets,
503 boolean install) {
504 osNodeService.completeNodes(COMPUTE).stream()
505 .filter(cNode -> cNode.dataIp() != null)
506 .forEach(cNode -> setRulesToGatewayWithRoutableSubnets(
507 cNode,
508 srcNatGw,
509 network.getProviderSegID(),
510 osSubnet,
511 routableSubnets,
Jian Li621f73c2018-12-15 01:49:22 +0900512 VXLAN,
Jian Li2d68c192018-12-13 15:52:59 +0900513 install));
514 }
515
516 private void setGatewayIcmpForGre(Subnet osSubnet,
517 OpenstackNode srcNatGw,
518 Network network,
519 Set<Subnet> routableSubnets,
520 boolean install) {
521 osNodeService.completeNodes(COMPUTE).stream()
522 .filter(cNode -> cNode.dataIp() != null)
523 .forEach(cNode -> setRulesToGatewayWithRoutableSubnets(
524 cNode,
525 srcNatGw,
526 network.getProviderSegID(),
527 osSubnet,
528 routableSubnets,
Jian Li621f73c2018-12-15 01:49:22 +0900529 GRE,
530 install));
531 }
532
533 private void setGatewayIcmpForGeneve(Subnet osSubnet,
534 OpenstackNode srcNatGw,
535 Network network,
536 Set<Subnet> routableSubnets,
537 boolean install) {
538 osNodeService.completeNodes(COMPUTE).stream()
539 .filter(cNode -> cNode.dataIp() != null)
540 .forEach(cNode -> setRulesToGatewayWithRoutableSubnets(
541 cNode,
542 srcNatGw,
543 network.getProviderSegID(),
544 osSubnet,
545 routableSubnets,
546 GENEVE,
Jian Li4d138702018-11-27 17:25:28 +0900547 install));
548 }
549
550 private void setGatewayIcmpForVlan(Subnet osSubnet,
551 OpenstackNode srcNatGw,
552 Network network,
553 Set<Subnet> routableSubnets,
554 boolean install) {
555 osNodeService.completeNodes(COMPUTE).stream()
556 .filter(cNode -> cNode.vlanPortNum() != null)
557 .forEach(cNode -> setRulesToGatewayWithRoutableSubnets(
558 cNode,
559 srcNatGw,
560 network.getProviderSegID(),
561 osSubnet,
562 routableSubnets,
SONA Project6bc5c4a2018-12-14 23:49:52 +0900563 VLAN,
Jian Li4d138702018-11-27 17:25:28 +0900564 install));
565 }
566
Hyunsun Moon44aac662017-02-18 02:07:01 +0900567 private void setInternalRoutes(Router osRouter, Subnet updatedSubnet, boolean install) {
SONA Project6bc5c4a2018-12-14 23:49:52 +0900568 Type netType = osNetworkAdminService.networkType(updatedSubnet.getNetworkId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900569 Set<Subnet> routableSubnets = routableSubnets(osRouter, updatedSubnet.getId());
Jian Lib6969502018-10-30 20:38:07 +0900570 String updatedSegmentId = getSegmentId(updatedSubnet);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900571
572 // installs rule from/to my subnet intentionally to fix ICMP failure
573 // to my subnet gateway if no external gateway added to the router
Hyunsun Moon0d457362017-06-27 17:19:41 +0900574 osNodeService.completeNodes(COMPUTE).forEach(cNode -> {
575 setInternalRouterRules(
576 cNode.intgBridge(),
Jian Lib6969502018-10-30 20:38:07 +0900577 updatedSegmentId,
578 updatedSegmentId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900579 IpPrefix.valueOf(updatedSubnet.getCidr()),
580 IpPrefix.valueOf(updatedSubnet.getCidr()),
SONA Project6bc5c4a2018-12-14 23:49:52 +0900581 netType,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900582 install
583 );
Hyunsun Moon44aac662017-02-18 02:07:01 +0900584
Hyunsun Moon0d457362017-06-27 17:19:41 +0900585 routableSubnets.forEach(subnet -> {
586 setInternalRouterRules(
587 cNode.intgBridge(),
Jian Lib6969502018-10-30 20:38:07 +0900588 updatedSegmentId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900589 getSegmentId(subnet),
590 IpPrefix.valueOf(updatedSubnet.getCidr()),
591 IpPrefix.valueOf(subnet.getCidr()),
SONA Project6bc5c4a2018-12-14 23:49:52 +0900592 netType,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900593 install
594 );
595 setInternalRouterRules(
596 cNode.intgBridge(),
597 getSegmentId(subnet),
Jian Lib6969502018-10-30 20:38:07 +0900598 updatedSegmentId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900599 IpPrefix.valueOf(subnet.getCidr()),
600 IpPrefix.valueOf(updatedSubnet.getCidr()),
SONA Project6bc5c4a2018-12-14 23:49:52 +0900601 netType,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900602 install
603 );
604 });
605 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900606
daniel parkee8700b2017-05-11 15:50:03 +0900607
Hyunsun Moon44aac662017-02-18 02:07:01 +0900608 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
609 routableSubnets.forEach(subnet -> log.debug(
610 updateStr + "route between subnet:{} and subnet:{}",
611 subnet.getCidr(),
612 updatedSubnet.getCidr()));
613 }
614
615 private Set<Subnet> routableSubnets(Router osRouter, String osSubnetId) {
616 Set<Subnet> osSubnets = osRouterService.routerInterfaces(osRouter.getId())
617 .stream()
618 .filter(iface -> !Objects.equals(iface.getSubnetId(), osSubnetId))
Jian Liedc8b762018-03-22 15:42:00 +0900619 .map(iface -> osNetworkAdminService.subnet(iface.getSubnetId()))
Hyunsun Moon44aac662017-02-18 02:07:01 +0900620 .collect(Collectors.toSet());
621 return ImmutableSet.copyOf(osSubnets);
622 }
623
daniel parkee8700b2017-05-11 15:50:03 +0900624 private String getSegmentId(Subnet osSubnet) {
Jian Liedc8b762018-03-22 15:42:00 +0900625 return osNetworkAdminService.network(osSubnet.getNetworkId()).getProviderSegID();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900626 }
627
628 private void setGatewayIcmpRule(IpAddress gatewayIp, DeviceId deviceId, boolean install) {
629 TrafficSelector selector = DefaultTrafficSelector.builder()
630 .matchEthType(Ethernet.TYPE_IPV4)
631 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900632 .matchIPDst(gatewayIp.getIp4Address().toIpPrefix())
Hyunsun Moon44aac662017-02-18 02:07:01 +0900633 .build();
634
635 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Jian Li4d5c5c32018-04-02 16:38:18 +0900636 .punt()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900637 .build();
638
sanghodc375372017-06-08 10:41:30 +0900639 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900640 appId,
641 deviceId,
642 selector,
643 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900644 PRIORITY_ICMP_RULE,
sanghodc375372017-06-08 10:41:30 +0900645 Constants.GW_COMMON_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900646 install);
647 }
648
Jian Li4d138702018-11-27 17:25:28 +0900649 private void setInternalRouterRules(DeviceId deviceId, String srcSegId, String dstSegId,
daniel parkee8700b2017-05-11 15:50:03 +0900650 IpPrefix srcSubnet, IpPrefix dstSubnet,
SONA Project6bc5c4a2018-12-14 23:49:52 +0900651 Type networkType, boolean install) {
Jian Li4d138702018-11-27 17:25:28 +0900652
daniel parkee8700b2017-05-11 15:50:03 +0900653 switch (networkType) {
654 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900655 case GRE:
Jian Li621f73c2018-12-15 01:49:22 +0900656 case GENEVE:
Jian Li2d68c192018-12-13 15:52:59 +0900657 setInternalRouterRulesForTunnel(deviceId, srcSegId, dstSegId,
Jian Li4d138702018-11-27 17:25:28 +0900658 srcSubnet, dstSubnet, install);
daniel parkee8700b2017-05-11 15:50:03 +0900659 break;
660 case VLAN:
Jian Li4d138702018-11-27 17:25:28 +0900661 setInternalRouterRulesForVlan(deviceId, srcSegId, dstSegId,
662 srcSubnet, dstSubnet, install);
daniel parkee8700b2017-05-11 15:50:03 +0900663 break;
664 default:
Jian Li4d138702018-11-27 17:25:28 +0900665 final String error = String.format("%s %s", ERR_UNSUPPORTED_NET_TYPE,
666 networkType.toString());
daniel parkee8700b2017-05-11 15:50:03 +0900667 throw new IllegalStateException(error);
668 }
669
Hyunsun Moon44aac662017-02-18 02:07:01 +0900670 }
671
Jian Li2d68c192018-12-13 15:52:59 +0900672 private void setInternalRouterRulesForTunnel(DeviceId deviceId,
673 String srcSegmentId,
674 String dstSegmentId,
675 IpPrefix srcSubnet,
676 IpPrefix dstSubnet,
677 boolean install) {
Jian Li4d138702018-11-27 17:25:28 +0900678 TrafficSelector selector;
679 TrafficTreatment treatment;
680 selector = DefaultTrafficSelector.builder()
681 .matchEthType(Ethernet.TYPE_IPV4)
682 .matchTunnelId(Long.parseLong(srcSegmentId))
683 .matchIPSrc(srcSubnet.getIp4Prefix())
684 .matchIPDst(dstSubnet.getIp4Prefix())
685 .build();
686
687 treatment = DefaultTrafficTreatment.builder()
688 .setTunnelId(Long.parseLong(dstSegmentId))
689 .transition(STAT_OUTBOUND_TABLE)
690 .build();
691
692 osFlowRuleService.setRule(
693 appId,
694 deviceId,
695 selector,
696 treatment,
697 PRIORITY_INTERNAL_ROUTING_RULE,
698 ROUTING_TABLE,
699 install);
700
701 selector = DefaultTrafficSelector.builder()
702 .matchEthType(Ethernet.TYPE_IPV4)
703 .matchTunnelId(Long.parseLong(dstSegmentId))
704 .matchIPSrc(srcSubnet.getIp4Prefix())
705 .matchIPDst(dstSubnet.getIp4Prefix())
706 .build();
707
708 treatment = DefaultTrafficTreatment.builder()
709 .setTunnelId(Long.parseLong(dstSegmentId))
710 .transition(STAT_OUTBOUND_TABLE)
711 .build();
712
713 osFlowRuleService.setRule(
714 appId,
715 deviceId,
716 selector,
717 treatment,
718 PRIORITY_INTERNAL_ROUTING_RULE,
719 ROUTING_TABLE,
720 install);
721 }
722
723 private void setInternalRouterRulesForVlan(DeviceId deviceId,
724 String srcSegmentId,
725 String dstSegmentId,
726 IpPrefix srcSubnet,
727 IpPrefix dstSubnet,
728 boolean install) {
729 TrafficSelector selector;
730 TrafficTreatment treatment;
731 selector = DefaultTrafficSelector.builder()
732 .matchEthType(Ethernet.TYPE_IPV4)
733 .matchVlanId(VlanId.vlanId(srcSegmentId))
734 .matchIPSrc(srcSubnet.getIp4Prefix())
735 .matchIPDst(dstSubnet.getIp4Prefix())
736 .build();
737
738 treatment = DefaultTrafficTreatment.builder()
739 .setVlanId(VlanId.vlanId(dstSegmentId))
740 .transition(STAT_OUTBOUND_TABLE)
741 .build();
742
743 osFlowRuleService.setRule(
744 appId,
745 deviceId,
746 selector,
747 treatment,
748 PRIORITY_INTERNAL_ROUTING_RULE,
749 ROUTING_TABLE,
750 install);
751
752 selector = DefaultTrafficSelector.builder()
753 .matchEthType(Ethernet.TYPE_IPV4)
754 .matchVlanId(VlanId.vlanId(dstSegmentId))
755 .matchIPSrc(srcSubnet.getIp4Prefix())
756 .matchIPDst(dstSubnet.getIp4Prefix())
757 .build();
758
759 treatment = DefaultTrafficTreatment.builder()
760 .setVlanId(VlanId.vlanId(dstSegmentId))
761 .transition(STAT_OUTBOUND_TABLE)
762 .build();
763
764 osFlowRuleService.setRule(
765 appId,
766 deviceId,
767 selector,
768 treatment,
769 PRIORITY_INTERNAL_ROUTING_RULE,
770 ROUTING_TABLE,
771 install);
772 }
773
Jian Li5ecfd1a2018-12-10 11:41:03 +0900774 private void setRulesToGateway(OpenstackNode osNode,
775 String segmentId,
776 IpPrefix srcSubnet,
SONA Project6bc5c4a2018-12-14 23:49:52 +0900777 Type networkType,
Jian Li5ecfd1a2018-12-10 11:41:03 +0900778 boolean install) {
779 OpenstackNode sourceNatGateway =
780 osNodeService.completeNodes(GATEWAY).stream().findFirst().orElse(null);
daniel parkb5817102018-02-15 00:18:51 +0900781
782 if (sourceNatGateway == null) {
783 return;
784 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900785
daniel parkee8700b2017-05-11 15:50:03 +0900786 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
787 .matchEthType(Ethernet.TYPE_IPV4)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900788 .matchIPSrc(srcSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900789 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
790
791 switch (networkType) {
792 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900793 case GRE:
Jian Li621f73c2018-12-15 01:49:22 +0900794 case GENEVE:
daniel parkee8700b2017-05-11 15:50:03 +0900795 sBuilder.matchTunnelId(Long.parseLong(segmentId));
daniel parkee8700b2017-05-11 15:50:03 +0900796 break;
797 case VLAN:
798 sBuilder.matchVlanId(VlanId.vlanId(segmentId));
daniel parkee8700b2017-05-11 15:50:03 +0900799 break;
800 default:
Jian Li71670d12018-03-02 21:31:07 +0900801 final String error = String.format("%s %s",
802 ERR_UNSUPPORTED_NET_TYPE,
daniel parkee8700b2017-05-11 15:50:03 +0900803 networkType.toString());
804 throw new IllegalStateException(error);
805 }
806
Daniel Parkc64b4c62018-05-09 18:13:39 +0900807 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
808
809 switch (networkType) {
810 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900811 case GRE:
Jian Li621f73c2018-12-15 01:49:22 +0900812 case GENEVE:
SONA Project6bc5c4a2018-12-14 23:49:52 +0900813 PortNumber portNum = tunnelPortNumByNetType(networkType, osNode);
Daniel Parkc64b4c62018-05-09 18:13:39 +0900814 tBuilder.extension(buildExtension(
815 deviceService,
816 osNode.intgBridge(),
817 sourceNatGateway.dataIp().getIp4Address()),
818 osNode.intgBridge())
Jian Li2d68c192018-12-13 15:52:59 +0900819 .setOutput(portNum);
Daniel Parkc64b4c62018-05-09 18:13:39 +0900820 break;
821
822 case VLAN:
823 tBuilder.setOutput(osNode.vlanPortNum());
824 break;
825
826 default:
827 break;
828 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900829
sanghodc375372017-06-08 10:41:30 +0900830 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900831 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900832 osNode.intgBridge(),
daniel parkee8700b2017-05-11 15:50:03 +0900833 sBuilder.build(),
Daniel Parkc64b4c62018-05-09 18:13:39 +0900834 tBuilder.build(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900835 PRIORITY_EXTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900836 ROUTING_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900837 install);
838 }
839
Jian Li5ecfd1a2018-12-10 11:41:03 +0900840 private void setRulesForSnatIngressRule(DeviceId deviceId,
841 Long vni,
842 IpPrefix destVmIp,
843 DeviceId dstDeviceId,
SONA Project6bc5c4a2018-12-14 23:49:52 +0900844 Type networkType,
Jian Li5ecfd1a2018-12-10 11:41:03 +0900845 boolean install) {
sangho072c4dd2017-05-17 10:45:21 +0900846
847 TrafficSelector selector = DefaultTrafficSelector.builder()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900848 .matchEthType(Ethernet.TYPE_IPV4)
sangho072c4dd2017-05-17 10:45:21 +0900849 .matchIPDst(destVmIp)
850 .build();
Hyunsun Moon0d457362017-06-27 17:19:41 +0900851
SONA Project6bc5c4a2018-12-14 23:49:52 +0900852 PortNumber portNum = tunnelPortNumByNetType(networkType,
Jian Li2d68c192018-12-13 15:52:59 +0900853 osNodeService.node(deviceId));
854
sangho072c4dd2017-05-17 10:45:21 +0900855 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
856 .setTunnelId(vni)
857 .extension(buildExtension(
858 deviceService,
859 deviceId,
860 osNodeService.node(dstDeviceId).dataIp().getIp4Address()),
861 deviceId)
Jian Li2d68c192018-12-13 15:52:59 +0900862 .setOutput(portNum)
sangho072c4dd2017-05-17 10:45:21 +0900863 .build();
daniel parkee8700b2017-05-11 15:50:03 +0900864
sanghodc375372017-06-08 10:41:30 +0900865 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900866 appId,
sangho072c4dd2017-05-17 10:45:21 +0900867 deviceId,
868 selector,
869 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900870 PRIORITY_EXTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900871 Constants.GW_COMMON_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900872 install);
873 }
874
Jian Li5ecfd1a2018-12-10 11:41:03 +0900875 private void setRulesToGatewayWithRoutableSubnets(OpenstackNode osNode,
876 OpenstackNode sourceNatGateway,
877 String segmentId,
878 Subnet updatedSubnet,
879 Set<Subnet> routableSubnets,
SONA Project6bc5c4a2018-12-14 23:49:52 +0900880 Type networkType,
Daniel Park51f9d1e2018-10-26 13:39:09 +0900881 boolean install) {
882 //At first we install flow rules to gateway with segId and gatewayIp of updated subnet
Jian Li5ecfd1a2018-12-10 11:41:03 +0900883 setRulesToGatewayWithDstIp(osNode, sourceNatGateway, segmentId,
Jian Li2d68c192018-12-13 15:52:59 +0900884 IpAddress.valueOf(updatedSubnet.getGateway()), networkType, install);
Daniel Park51f9d1e2018-10-26 13:39:09 +0900885
886 routableSubnets.forEach(subnet -> {
887 setRulesToGatewayWithDstIp(osNode, sourceNatGateway,
888 segmentId, IpAddress.valueOf(subnet.getGateway()),
Jian Li2d68c192018-12-13 15:52:59 +0900889 networkType, install);
Daniel Park51f9d1e2018-10-26 13:39:09 +0900890
891 Network network = osNetworkAdminService.network(subnet.getNetworkId());
892 setRulesToGatewayWithDstIp(osNode, sourceNatGateway,
893 network.getProviderSegID(), IpAddress.valueOf(updatedSubnet.getGateway()),
Jian Li2d68c192018-12-13 15:52:59 +0900894 networkType, install);
Daniel Park51f9d1e2018-10-26 13:39:09 +0900895 });
896 }
897
Jian Li5ecfd1a2018-12-10 11:41:03 +0900898 private void setRulesToGatewayWithDstIp(OpenstackNode osNode,
899 OpenstackNode sourceNatGateway,
900 String segmentId,
901 IpAddress dstIp,
SONA Project6bc5c4a2018-12-14 23:49:52 +0900902 Type networkType,
Jian Li5ecfd1a2018-12-10 11:41:03 +0900903 boolean install) {
Daniel Parkc64b4c62018-05-09 18:13:39 +0900904 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
905 .matchEthType(Ethernet.TYPE_IPV4)
906 .matchIPDst(dstIp.getIp4Address().toIpPrefix());
907
Daniel Parkc64b4c62018-05-09 18:13:39 +0900908 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
909
Jian Li2d68c192018-12-13 15:52:59 +0900910 switch (networkType) {
Daniel Parkc64b4c62018-05-09 18:13:39 +0900911 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900912 case GRE:
Jian Li621f73c2018-12-15 01:49:22 +0900913 case GENEVE:
Daniel Park51f9d1e2018-10-26 13:39:09 +0900914 sBuilder.matchTunnelId(Long.parseLong(segmentId));
Jian Li2d68c192018-12-13 15:52:59 +0900915
SONA Project6bc5c4a2018-12-14 23:49:52 +0900916 PortNumber portNum = tunnelPortNumByNetType(networkType, osNode);
Jian Li2d68c192018-12-13 15:52:59 +0900917
Daniel Parkc64b4c62018-05-09 18:13:39 +0900918 tBuilder.extension(buildExtension(
daniel parkb5817102018-02-15 00:18:51 +0900919 deviceService,
920 osNode.intgBridge(),
921 sourceNatGateway.dataIp().getIp4Address()),
922 osNode.intgBridge())
Jian Li2d68c192018-12-13 15:52:59 +0900923 .setOutput(portNum);
Daniel Parkc64b4c62018-05-09 18:13:39 +0900924 break;
Daniel Parkc64b4c62018-05-09 18:13:39 +0900925 case VLAN:
Daniel Park51f9d1e2018-10-26 13:39:09 +0900926 sBuilder.matchVlanId(VlanId.vlanId(segmentId));
Daniel Parkc64b4c62018-05-09 18:13:39 +0900927 tBuilder.setOutput(osNode.vlanPortNum());
928 break;
929
930 default:
931 break;
932 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900933
sanghodc375372017-06-08 10:41:30 +0900934 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900935 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900936 osNode.intgBridge(),
Daniel Parkc64b4c62018-05-09 18:13:39 +0900937 sBuilder.build(),
938 tBuilder.build(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900939 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900940 ROUTING_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900941 install);
942 }
943
Jian Li5ecfd1a2018-12-10 11:41:03 +0900944 private void setOvsNatIngressRule(DeviceId deviceId,
945 IpPrefix cidr,
946 MacAddress dstMac,
947 boolean install) {
sangho072c4dd2017-05-17 10:45:21 +0900948
949 TrafficSelector selector = DefaultTrafficSelector.builder()
950 .matchEthType(Ethernet.TYPE_IPV4)
951 .matchIPDst(cidr)
952 .build();
953
Jian Liedc8b762018-03-22 15:42:00 +0900954 ExtensionTreatment natTreatment = RulePopulatorUtil
955 .niciraConnTrackTreatmentBuilder(driverService, deviceId)
sangho072c4dd2017-05-17 10:45:21 +0900956 .commit(false)
957 .natAction(true)
958 .table((short) 0)
959 .build();
960
961 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
962 .setEthDst(dstMac)
963 .extension(natTreatment, deviceId)
964 .build();
965
966 osFlowRuleService.setRule(
967 appId,
968 deviceId,
969 selector,
970 treatment,
sanghoe765ce22017-06-23 17:54:57 +0900971 PRIORITY_STATEFUL_SNAT_RULE,
sangho072c4dd2017-05-17 10:45:21 +0900972 GW_COMMON_TABLE,
973 install);
974 }
975
Jian Li5ecfd1a2018-12-10 11:41:03 +0900976 private void setOvsNatEgressRule(DeviceId deviceId,
977 IpAddress natAddress,
978 long vni,
979 PortNumber output,
sangho072c4dd2017-05-17 10:45:21 +0900980 boolean install) {
981
982 TrafficSelector selector = DefaultTrafficSelector.builder()
983 .matchEthType(Ethernet.TYPE_IPV4)
984 .matchEthDst(DEFAULT_GATEWAY_MAC)
985 .matchTunnelId(vni)
986 .build();
987
Jian Liedc8b762018-03-22 15:42:00 +0900988 ExtensionTreatment natTreatment = RulePopulatorUtil
989 .niciraConnTrackTreatmentBuilder(driverService, deviceId)
sangho072c4dd2017-05-17 10:45:21 +0900990 .commit(true)
991 .natAction(true)
992 .natIp(natAddress)
993 .build();
994
995 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
996 .extension(natTreatment, deviceId)
997 .setEthDst(DEFAULT_EXTERNAL_ROUTER_MAC)
998 .setEthSrc(DEFAULT_GATEWAY_MAC)
999 .setOutput(output)
1000 .build();
1001
1002 osFlowRuleService.setRule(
1003 appId,
1004 deviceId,
1005 selector,
1006 treatment,
sanghoe765ce22017-06-23 17:54:57 +09001007 PRIORITY_STATEFUL_SNAT_RULE,
sangho072c4dd2017-05-17 10:45:21 +09001008 GW_COMMON_TABLE,
1009 install);
1010 }
1011
Jian Li5ecfd1a2018-12-10 11:41:03 +09001012 private void setRulesToController(DeviceId deviceId,
1013 String segmentId,
1014 IpPrefix srcSubnet,
SONA Project6bc5c4a2018-12-14 23:49:52 +09001015 Type networkType,
Jian Li5ecfd1a2018-12-10 11:41:03 +09001016 boolean install) {
sanghoe765ce22017-06-23 17:54:57 +09001017 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
1018 .matchEthType(Ethernet.TYPE_IPV4)
Daniel Parkc64b4c62018-05-09 18:13:39 +09001019 .matchIPSrc(srcSubnet)
1020 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
1021
sanghoe765ce22017-06-23 17:54:57 +09001022 switch (networkType) {
1023 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +09001024 case GRE:
Jian Li621f73c2018-12-15 01:49:22 +09001025 case GENEVE:
Daniel Parkc64b4c62018-05-09 18:13:39 +09001026 sBuilder.matchTunnelId(Long.parseLong(segmentId));
sanghoe765ce22017-06-23 17:54:57 +09001027 break;
1028 case VLAN:
Daniel Parkc64b4c62018-05-09 18:13:39 +09001029 sBuilder.matchVlanId(VlanId.vlanId(segmentId));
sanghoe765ce22017-06-23 17:54:57 +09001030 break;
1031 default:
Jian Li71670d12018-03-02 21:31:07 +09001032 final String error = String.format("%s %s",
1033 ERR_UNSUPPORTED_NET_TYPE,
sanghoe765ce22017-06-23 17:54:57 +09001034 networkType.toString());
1035 throw new IllegalStateException(error);
1036 }
1037
Daniel Parkc64b4c62018-05-09 18:13:39 +09001038 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
sanghoe765ce22017-06-23 17:54:57 +09001039
SONA Project6bc5c4a2018-12-14 23:49:52 +09001040 if (networkType == VLAN) {
sanghoe765ce22017-06-23 17:54:57 +09001041 tBuilder.popVlan();
1042 }
1043
Jian Li4d5c5c32018-04-02 16:38:18 +09001044 tBuilder.punt();
sanghoe765ce22017-06-23 17:54:57 +09001045
1046 osFlowRuleService.setRule(
1047 appId,
1048 deviceId,
1049 sBuilder.build(),
1050 tBuilder.build(),
1051 PRIORITY_EXTERNAL_ROUTING_RULE,
1052 GW_COMMON_TABLE,
1053 install);
sanghoe765ce22017-06-23 17:54:57 +09001054 }
sangho072c4dd2017-05-17 10:45:21 +09001055
Jian Li5ecfd1a2018-12-10 11:41:03 +09001056 private void setRouterAdminRules(String segmentId,
SONA Project6bc5c4a2018-12-14 23:49:52 +09001057 Type networkType,
Jian Li5ecfd1a2018-12-10 11:41:03 +09001058 boolean install) {
Frank Wang245a6822017-06-14 09:51:35 +08001059 TrafficTreatment treatment;
1060 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
1061 .matchEthType(Ethernet.TYPE_IPV4);
1062
1063 switch (networkType) {
1064 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +09001065 case GRE:
Jian Li621f73c2018-12-15 01:49:22 +09001066 case GENEVE:
Frank Wang245a6822017-06-14 09:51:35 +08001067 sBuilder.matchTunnelId(Long.parseLong(segmentId));
1068 break;
1069 case VLAN:
1070 sBuilder.matchVlanId(VlanId.vlanId(segmentId));
1071 break;
1072 default:
Jian Li71670d12018-03-02 21:31:07 +09001073 final String error = String.format("%s %s",
1074 ERR_UNSUPPORTED_NET_TYPE,
Frank Wang245a6822017-06-14 09:51:35 +08001075 networkType.toString());
1076 throw new IllegalStateException(error);
1077 }
1078
1079 treatment = DefaultTrafficTreatment.builder()
1080 .drop()
1081 .build();
1082
1083 osNodeService.completeNodes().stream()
1084 .filter(osNode -> osNode.type() == COMPUTE)
1085 .forEach(osNode -> {
1086 osFlowRuleService.setRule(
1087 appId,
1088 osNode.intgBridge(),
1089 sBuilder.build(),
1090 treatment,
1091 PRIORITY_ADMIN_RULE,
1092 ROUTING_TABLE,
1093 install);
1094 });
1095 }
1096
Hyunsun Moon44aac662017-02-18 02:07:01 +09001097 private class InternalRouterEventListener implements OpenstackRouterListener {
1098
Jian Li34220ea2018-11-14 01:30:24 +09001099 private boolean isRelevantHelper() {
1100 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001101 }
1102
1103 // FIXME only one leader in the cluster should process
1104 @Override
1105 public void event(OpenstackRouterEvent event) {
1106 switch (event.type()) {
1107 case OPENSTACK_ROUTER_CREATED:
Jian Li4d138702018-11-27 17:25:28 +09001108 eventExecutor.execute(() -> processRouterCreation(event));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001109 break;
1110 case OPENSTACK_ROUTER_UPDATED:
Jian Li4d138702018-11-27 17:25:28 +09001111 eventExecutor.execute(() -> processRouterUpdate(event));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001112 break;
1113 case OPENSTACK_ROUTER_REMOVED:
Jian Li4d138702018-11-27 17:25:28 +09001114 eventExecutor.execute(() -> processRouterRemoval(event));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001115 break;
1116 case OPENSTACK_ROUTER_INTERFACE_ADDED:
Jian Li4d138702018-11-27 17:25:28 +09001117 eventExecutor.execute(() -> processRouterIntfCreation(event));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001118 break;
1119 case OPENSTACK_ROUTER_INTERFACE_UPDATED:
Jian Li4d138702018-11-27 17:25:28 +09001120 eventExecutor.execute(() -> processRouterIntfUpdate(event));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001121 break;
1122 case OPENSTACK_ROUTER_INTERFACE_REMOVED:
Jian Li4d138702018-11-27 17:25:28 +09001123 eventExecutor.execute(() -> processRouterIntfRemoval(event));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001124 break;
1125 case OPENSTACK_ROUTER_GATEWAY_ADDED:
Jian Li32b03622018-11-06 17:54:24 +09001126 log.debug("Router external gateway {} added",
1127 event.externalGateway().getNetworkId());
Ray Milkey08932a72018-02-20 15:34:38 -08001128 break;
Hyunsun Moon44aac662017-02-18 02:07:01 +09001129 case OPENSTACK_ROUTER_GATEWAY_REMOVED:
Jian Li32b03622018-11-06 17:54:24 +09001130 log.debug("Router external gateway {} removed",
1131 event.externalGateway().getNetworkId());
Ray Milkey08932a72018-02-20 15:34:38 -08001132 break;
Hyunsun Moon44aac662017-02-18 02:07:01 +09001133 case OPENSTACK_FLOATING_IP_CREATED:
1134 case OPENSTACK_FLOATING_IP_UPDATED:
1135 case OPENSTACK_FLOATING_IP_REMOVED:
1136 case OPENSTACK_FLOATING_IP_ASSOCIATED:
1137 case OPENSTACK_FLOATING_IP_DISASSOCIATED:
1138 default:
1139 // do nothing for the other events
1140 break;
1141 }
1142 }
Jian Li4d138702018-11-27 17:25:28 +09001143
1144 private void processRouterCreation(OpenstackRouterEvent event) {
1145 if (!isRelevantHelper()) {
1146 return;
1147 }
1148
1149 log.debug("Router(name:{}, ID:{}) is created",
1150 event.subject().getName(),
1151 event.subject().getId());
1152
1153 routerUpdated(event.subject());
1154 }
1155
1156 private void processRouterUpdate(OpenstackRouterEvent event) {
1157 if (!isRelevantHelper()) {
1158 return;
1159 }
1160
1161 log.debug("Router(name:{}, ID:{}) is updated",
1162 event.subject().getName(),
1163 event.subject().getId());
1164
1165 routerUpdated(event.subject());
1166 }
1167
1168 private void processRouterRemoval(OpenstackRouterEvent event) {
1169 if (!isRelevantHelper()) {
1170 return;
1171 }
1172
1173 log.debug("Router(name:{}, ID:{}) is removed",
1174 event.subject().getName(),
1175 event.subject().getId());
1176
1177 routerRemove(event.subject());
1178 }
1179
1180 private void processRouterIntfCreation(OpenstackRouterEvent event) {
1181 if (!isRelevantHelper()) {
1182 return;
1183 }
1184
1185 log.debug("Router interface {} added to router {}",
1186 event.routerIface().getPortId(),
1187 event.routerIface().getId());
1188
1189 routerIfaceAdded(event.subject(), event.routerIface());
1190 }
1191
1192 private void processRouterIntfUpdate(OpenstackRouterEvent event) {
1193 log.debug("Router interface {} on {} updated",
1194 event.routerIface().getPortId(),
1195 event.routerIface().getId());
1196 }
1197
1198 private void processRouterIntfRemoval(OpenstackRouterEvent event) {
1199 if (!isRelevantHelper()) {
1200 return;
1201 }
1202
1203 log.debug("Router interface {} removed from router {}",
1204 event.routerIface().getPortId(),
1205 event.routerIface().getId());
1206
1207 routerIfaceRemoved(event.subject(), event.routerIface());
1208 }
Hyunsun Moon44aac662017-02-18 02:07:01 +09001209 }
1210
1211 private class InternalNodeEventListener implements OpenstackNodeListener {
1212
Jian Li34220ea2018-11-14 01:30:24 +09001213 private boolean isRelevantHelper() {
1214 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001215 }
1216
1217 @Override
1218 public void event(OpenstackNodeEvent event) {
1219 OpenstackNode osNode = event.subject();
Hyunsun Moon44aac662017-02-18 02:07:01 +09001220 switch (event.type()) {
Hyunsun Moon0d457362017-06-27 17:19:41 +09001221 case OPENSTACK_NODE_COMPLETE:
1222 case OPENSTACK_NODE_INCOMPLETE:
Daniel Park6ed9cf02018-06-27 19:07:44 +09001223 case OPENSTACK_NODE_UPDATED:
1224 case OPENSTACK_NODE_REMOVED:
Hyunsun Moon44aac662017-02-18 02:07:01 +09001225 eventExecutor.execute(() -> {
Jian Li34220ea2018-11-14 01:30:24 +09001226 if (!isRelevantHelper()) {
1227 return;
1228 }
Jian Li4d138702018-11-27 17:25:28 +09001229 reconfigureRouters(osNode);
Hyunsun Moon44aac662017-02-18 02:07:01 +09001230 });
1231 break;
Hyunsun Moon0d457362017-06-27 17:19:41 +09001232 case OPENSTACK_NODE_CREATED:
Hyunsun Moon44aac662017-02-18 02:07:01 +09001233 default:
1234 break;
1235 }
1236 }
1237
Jian Li4d138702018-11-27 17:25:28 +09001238 private void reconfigureRouters(OpenstackNode osNode) {
Hyunsun Moon44aac662017-02-18 02:07:01 +09001239 osRouterService.routers().forEach(osRouter -> {
1240 routerUpdated(osRouter);
1241 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
1242 routerIfaceAdded(osRouter, iface);
1243 });
1244 });
Jian Li4d138702018-11-27 17:25:28 +09001245 log.info("Reconfigure routers for {}", osNode.hostname());
Hyunsun Moon44aac662017-02-18 02:07:01 +09001246 }
1247 }
sangho072c4dd2017-05-17 10:45:21 +09001248
1249 private class InternalInstancePortListener implements InstancePortListener {
1250
Jian Li34220ea2018-11-14 01:30:24 +09001251 private boolean isRelevantHelper(InstancePortEvent event) {
1252 return mastershipService.isLocalMaster(event.subject().deviceId());
sangho072c4dd2017-05-17 10:45:21 +09001253 }
1254
1255 @Override
1256 public void event(InstancePortEvent event) {
1257 InstancePort instPort = event.subject();
1258 switch (event.type()) {
sangho072c4dd2017-05-17 10:45:21 +09001259 case OPENSTACK_INSTANCE_PORT_DETECTED:
Jian Liec5c32b2018-07-13 14:28:58 +09001260 case OPENSTACK_INSTANCE_PORT_UPDATED:
Jian Li4d138702018-11-27 17:25:28 +09001261 eventExecutor.execute(() ->
1262 processInstancePortDetection(event, instPort));
sangho072c4dd2017-05-17 10:45:21 +09001263 break;
1264 case OPENSTACK_INSTANCE_PORT_VANISHED:
Jian Li4d138702018-11-27 17:25:28 +09001265 eventExecutor.execute(() ->
1266 processInstancePortRemoval(event, instPort));
Jian Liec5c32b2018-07-13 14:28:58 +09001267 break;
1268 case OPENSTACK_INSTANCE_MIGRATION_STARTED:
Jian Li4d138702018-11-27 17:25:28 +09001269 eventExecutor.execute(() ->
1270 processInstanceMigrationStart(event, instPort));
sangho072c4dd2017-05-17 10:45:21 +09001271 break;
Jian Li24ec59f2018-05-23 19:01:25 +09001272 case OPENSTACK_INSTANCE_MIGRATION_ENDED:
Jian Li4d138702018-11-27 17:25:28 +09001273 eventExecutor.execute(() ->
1274 processInstanceMigrationEnd(event, instPort));
Jian Li24ec59f2018-05-23 19:01:25 +09001275 break;
sangho072c4dd2017-05-17 10:45:21 +09001276 default:
1277 break;
1278 }
1279 }
1280
Jian Li4d138702018-11-27 17:25:28 +09001281 private void processInstancePortDetection(InstancePortEvent event,
1282 InstancePort instPort) {
1283 if (!isRelevantHelper(event)) {
1284 return;
1285 }
1286
1287 log.info("RoutingHandler: Instance port detected MAC:{} IP:{}",
1288 instPort.macAddress(),
1289 instPort.ipAddress());
1290
1291 instPortDetected(event.subject());
1292 }
1293
1294 private void processInstancePortRemoval(InstancePortEvent event,
1295 InstancePort instPort) {
1296 if (!isRelevantHelper(event)) {
1297 return;
1298 }
1299
1300 log.info("RoutingHandler: Instance port vanished MAC:{} IP:{}",
1301 instPort.macAddress(),
1302 instPort.ipAddress());
1303
1304 instPortRemoved(event.subject());
1305 }
1306
1307 private void processInstanceMigrationStart(InstancePortEvent event,
1308 InstancePort instPort) {
1309 if (!isRelevantHelper(event)) {
1310 return;
1311 }
1312
1313 log.info("RoutingHandler: Migration started for MAC:{} IP:{}",
1314 instPort.macAddress(),
1315 instPort.ipAddress());
1316
1317 instPortDetected(instPort);
1318 }
1319
1320 private void processInstanceMigrationEnd(InstancePortEvent event,
1321 InstancePort instPort) {
1322 log.info("RoutingHandler: Migration finished for MAC:{} IP:{}",
1323 instPort.macAddress(),
1324 instPort.ipAddress());
1325 // TODO: need to reconfigure rules to point to update VM
1326 }
1327
sangho072c4dd2017-05-17 10:45:21 +09001328 private void instPortDetected(InstancePort instPort) {
Jian Li4d138702018-11-27 17:25:28 +09001329 Network network = osNetworkAdminService.network(instPort.networkId());
SONA Project6bc5c4a2018-12-14 23:49:52 +09001330 Type netType = osNetworkAdminService.networkType(instPort.networkId());
1331
1332 if (netType == FLAT) {
daniel park796c2eb2018-03-22 17:01:51 +09001333 return;
1334 }
Daniel Parkc64b4c62018-05-09 18:13:39 +09001335
1336 if (useStatefulSnat) {
1337 osNodeService.completeNodes(GATEWAY)
1338 .forEach(gwNode -> setRulesForSnatIngressRule(
1339 gwNode.intgBridge(),
Jian Li4d138702018-11-27 17:25:28 +09001340 Long.parseLong(network.getProviderSegID()),
1341 IpPrefix.valueOf(instPort.ipAddress(), VM_PREFIX),
SONA Project6bc5c4a2018-12-14 23:49:52 +09001342 instPort.deviceId(), netType, true));
Daniel Parkc64b4c62018-05-09 18:13:39 +09001343 }
sangho072c4dd2017-05-17 10:45:21 +09001344 }
1345
1346 private void instPortRemoved(InstancePort instPort) {
Jian Li4d138702018-11-27 17:25:28 +09001347 Network network = osNetworkAdminService.network(instPort.networkId());
SONA Project6bc5c4a2018-12-14 23:49:52 +09001348 Type netType = osNetworkAdminService.networkType(instPort.networkId());
1349
1350 if (netType == FLAT) {
daniel park796c2eb2018-03-22 17:01:51 +09001351 return;
1352 }
Daniel Parkc64b4c62018-05-09 18:13:39 +09001353
1354 if (useStatefulSnat) {
1355 osNodeService.completeNodes(GATEWAY)
1356 .forEach(gwNode -> setRulesForSnatIngressRule(
1357 gwNode.intgBridge(),
Jian Li4d138702018-11-27 17:25:28 +09001358 Long.parseLong(network.getProviderSegID()),
1359 IpPrefix.valueOf(instPort.ipAddress(), VM_PREFIX),
SONA Project6bc5c4a2018-12-14 23:49:52 +09001360 instPort.deviceId(), netType, false));
Daniel Parkc64b4c62018-05-09 18:13:39 +09001361 }
sangho072c4dd2017-05-17 10:45:21 +09001362 }
1363 }
Hyunsun Moon44aac662017-02-18 02:07:01 +09001364}