blob: bc02119fe28ab179f199199b4709c57ff44e3568 [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;
99import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.VLAN;
Ray Milkey8e406512018-10-24 15:56:50 -0700100import static org.onosproject.openstacknetworking.impl.OsgiPropertyConstants.USE_STATEFUL_SNAT;
101import static org.onosproject.openstacknetworking.impl.OsgiPropertyConstants.USE_STATEFUL_SNAT_DEFAULT;
Jian Li2d68c192018-12-13 15:52:59 +0900102import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.tunnelPortNumByNetType;
Jian Li26949762018-03-30 15:46:37 +0900103import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900104import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
105import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900106
107/**
108 * Handles OpenStack router events.
109 */
Ray Milkey8e406512018-10-24 15:56:50 -0700110@Component(
111 immediate = true,
112 property = {
113 USE_STATEFUL_SNAT + ":Boolean=" + USE_STATEFUL_SNAT_DEFAULT
114 }
115)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900116public class OpenstackRoutingHandler {
117
118 private final Logger log = LoggerFactory.getLogger(getClass());
119
120 private static final String MSG_ENABLED = "Enabled ";
121 private static final String MSG_DISABLED = "Disabled ";
daniel parkee8700b2017-05-11 15:50:03 +0900122 private static final String ERR_UNSUPPORTED_NET_TYPE = "Unsupported network type";
sanghoe765ce22017-06-23 17:54:57 +0900123
Jian Li4d138702018-11-27 17:25:28 +0900124 private static final int VM_PREFIX = 32;
125
Ray Milkey8e406512018-10-24 15:56:50 -0700126 /** Use Stateful SNAT for source NATing. */
127 private boolean useStatefulSnat = USE_STATEFUL_SNAT_DEFAULT;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900128
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700129 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900130 protected CoreService coreService;
131
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700132 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900133 protected LeadershipService leadershipService;
134
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700135 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900136 protected ClusterService clusterService;
137
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700138 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900139 protected OpenstackNodeService osNodeService;
140
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700141 @Reference(cardinality = ReferenceCardinality.MANDATORY)
daniel park32b42202018-03-14 16:53:44 +0900142 protected OpenstackNetworkAdminService osNetworkAdminService;
143
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700144 @Reference(cardinality = ReferenceCardinality.MANDATORY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900145 protected OpenstackRouterService osRouterService;
146
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700147 @Reference(cardinality = ReferenceCardinality.MANDATORY)
sangho072c4dd2017-05-17 10:45:21 +0900148 protected InstancePortService instancePortService;
149
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700150 @Reference(cardinality = ReferenceCardinality.MANDATORY)
sangho072c4dd2017-05-17 10:45:21 +0900151 protected DeviceService deviceService;
152
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700153 @Reference(cardinality = ReferenceCardinality.MANDATORY)
sanghodc375372017-06-08 10:41:30 +0900154 protected OpenstackFlowRuleService osFlowRuleService;
155
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700156 @Reference(cardinality = ReferenceCardinality.MANDATORY)
sangho072c4dd2017-05-17 10:45:21 +0900157 protected MastershipService mastershipService;
158
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700159 @Reference(cardinality = ReferenceCardinality.MANDATORY)
sangho072c4dd2017-05-17 10:45:21 +0900160 protected DriverService driverService;
161
Ray Milkeyd84f89b2018-08-17 14:54:17 -0700162 @Reference(cardinality = ReferenceCardinality.MANDATORY)
sanghoe765ce22017-06-23 17:54:57 +0900163 protected ComponentConfigService configService;
164
Hyunsun Moon44aac662017-02-18 02:07:01 +0900165 private final ExecutorService eventExecutor = newSingleThreadScheduledExecutor(
166 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
167 private final OpenstackNodeListener osNodeListener = new InternalNodeEventListener();
168 private final OpenstackRouterListener osRouterListener = new InternalRouterEventListener();
sangho072c4dd2017-05-17 10:45:21 +0900169 private final InstancePortListener instancePortListener = new InternalInstancePortListener();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900170
171 private ApplicationId appId;
172 private NodeId localNodeId;
173
174 @Activate
175 protected void activate() {
176 appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
177 localNodeId = clusterService.getLocalNode().id();
178 leadershipService.runForLeadership(appId.name());
179 osNodeService.addListener(osNodeListener);
180 osRouterService.addListener(osRouterListener);
sangho072c4dd2017-05-17 10:45:21 +0900181 instancePortService.addListener(instancePortListener);
sanghoe765ce22017-06-23 17:54:57 +0900182 configService.registerProperties(getClass());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900183
184 log.info("Started");
185 }
186
187 @Deactivate
188 protected void deactivate() {
189 osRouterService.removeListener(osRouterListener);
190 osNodeService.removeListener(osNodeListener);
sangho072c4dd2017-05-17 10:45:21 +0900191 instancePortService.removeListener(instancePortListener);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900192 leadershipService.withdraw(appId.name());
sanghoe765ce22017-06-23 17:54:57 +0900193 configService.unregisterProperties(getClass(), false);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900194 eventExecutor.shutdown();
195
196 log.info("Stopped");
197 }
198
sanghoe765ce22017-06-23 17:54:57 +0900199 @Modified
200 protected void modified(ComponentContext context) {
201 Dictionary<?, ?> properties = context.getProperties();
202 Boolean flag;
203
Ray Milkey8e406512018-10-24 15:56:50 -0700204 flag = Tools.isPropertyEnabled(properties, USE_STATEFUL_SNAT);
sanghoe765ce22017-06-23 17:54:57 +0900205 if (flag == null) {
206 log.info("useStatefulSnat is not configured, " +
207 "using current value of {}", useStatefulSnat);
208 } else {
209 useStatefulSnat = flag;
210 log.info("Configured. useStatefulSnat is {}",
211 useStatefulSnat ? "enabled" : "disabled");
212 }
213
214 resetSnatRules();
215 }
216
Hyunsun Moon44aac662017-02-18 02:07:01 +0900217 private void routerUpdated(Router osRouter) {
218 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
Frank Wang245a6822017-06-14 09:51:35 +0800219 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
Jian Li5ecfd1a2018-12-10 11:41:03 +0900220 Network network = osNetworkAdminService.network(
221 osNetworkAdminService.subnet(iface.getSubnetId())
Frank Wang245a6822017-06-14 09:51:35 +0800222 .getNetworkId());
SONA Project6bc5c4a2018-12-14 23:49:52 +0900223 Type netType = osNetworkAdminService.networkType(
224 osNetworkAdminService.subnet(iface.getSubnetId())
225 .getNetworkId());
Jian Li5ecfd1a2018-12-10 11:41:03 +0900226 setRouterAdminRules(network.getProviderSegID(),
SONA Project6bc5c4a2018-12-14 23:49:52 +0900227 netType, !osRouter.isAdminStateUp());
Frank Wang245a6822017-06-14 09:51:35 +0800228 });
229
Jian Li5ecfd1a2018-12-10 11:41:03 +0900230 ExternalPeerRouter externalPeerRouter =
231 osNetworkAdminService.externalPeerRouter(exGateway);
Jian Li5e2ad4a2018-07-16 13:40:53 +0900232 VlanId vlanId = externalPeerRouter == null ? VlanId.NONE : externalPeerRouter.vlanId();
daniel park576969a2018-03-09 07:07:41 +0900233
Hyunsun Moon44aac662017-02-18 02:07:01 +0900234 if (exGateway == null) {
Daniel Park613ac372018-06-28 14:30:11 +0900235 deleteUnassociatedExternalPeerRouter();
Jian Li5ecfd1a2018-12-10 11:41:03 +0900236 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface ->
237 setSourceNat(iface, false));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900238 } else {
daniel park32b42202018-03-14 16:53:44 +0900239 osNetworkAdminService.deriveExternalPeerRouterMac(exGateway, osRouter, vlanId);
daniel park576969a2018-03-09 07:07:41 +0900240 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface ->
241 setSourceNat(iface, exGateway.isEnableSnat()));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900242 }
243 }
244
Daniel Park613ac372018-06-28 14:30:11 +0900245 private void deleteUnassociatedExternalPeerRouter() {
246 log.trace("Deleting unassociated external peer router");
247
248 try {
249 Set<String> routerIps = Sets.newConcurrentHashSet();
250
251 osRouterService.routers().stream()
252 .filter(router -> getGatewayIpAddress(router) != null)
253 .map(router -> getGatewayIpAddress(router).toString())
254 .forEach(routerIps::add);
255
256 osNetworkAdminService.externalPeerRouters().stream()
257 .filter(externalPeerRouter ->
Jian Li5e2ad4a2018-07-16 13:40:53 +0900258 !routerIps.contains(externalPeerRouter.ipAddress().toString()))
Daniel Park613ac372018-06-28 14:30:11 +0900259 .forEach(externalPeerRouter -> {
260 osNetworkAdminService
Jian Li5ecfd1a2018-12-10 11:41:03 +0900261 .deleteExternalPeerRouter(
262 externalPeerRouter.ipAddress().toString());
Daniel Park613ac372018-06-28 14:30:11 +0900263 log.trace("Deleted unassociated external peer router {}",
Jian Li5e2ad4a2018-07-16 13:40:53 +0900264 externalPeerRouter.ipAddress().toString());
Daniel Park613ac372018-06-28 14:30:11 +0900265 });
266 } catch (Exception e) {
267 log.error("Exception occurred because of {}", e.toString());
268 }
269 }
270
Frank Wang245a6822017-06-14 09:51:35 +0800271 private void routerRemove(Router osRouter) {
272 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
Jian Li5ecfd1a2018-12-10 11:41:03 +0900273 Network network = osNetworkAdminService.network(
274 osNetworkAdminService.subnet(iface.getSubnetId())
Frank Wang245a6822017-06-14 09:51:35 +0800275 .getNetworkId());
SONA Project6bc5c4a2018-12-14 23:49:52 +0900276 Type netType = osNetworkAdminService.networkType(
277 osNetworkAdminService.subnet(iface.getSubnetId())
278 .getNetworkId());
279 setRouterAdminRules(network.getProviderSegID(), netType, false);
Frank Wang245a6822017-06-14 09:51:35 +0800280 });
281 }
282
Hyunsun Moon44aac662017-02-18 02:07:01 +0900283 private void routerIfaceAdded(Router osRouter, RouterInterface osRouterIface) {
Jian Liedc8b762018-03-22 15:42:00 +0900284 Subnet osSubnet = osNetworkAdminService.subnet(osRouterIface.getSubnetId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900285 if (osSubnet == null) {
286 final String error = String.format(
Jian Li71670d12018-03-02 21:31:07 +0900287 "Failed to set flows for router %s: subnet %s does not exist",
Hyunsun Moon44aac662017-02-18 02:07:01 +0900288 osRouterIface.getId(),
289 osRouterIface.getSubnetId());
290 throw new IllegalStateException(error);
291 }
Frank Wang245a6822017-06-14 09:51:35 +0800292
293 if (!osRouter.isAdminStateUp()) {
Jian Liedc8b762018-03-22 15:42:00 +0900294 Network network = osNetworkAdminService.network(osSubnet.getNetworkId());
SONA Project6bc5c4a2018-12-14 23:49:52 +0900295 Type netType = osNetworkAdminService.networkType(osSubnet.getNetworkId());
296 setRouterAdminRules(network.getProviderSegID(), netType, true);
Frank Wang245a6822017-06-14 09:51:35 +0800297 }
298
Hyunsun Moon44aac662017-02-18 02:07:01 +0900299 setInternalRoutes(osRouter, osSubnet, true);
Daniel Park51f9d1e2018-10-26 13:39:09 +0900300 setGatewayIcmp(osSubnet, osRouter, true);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900301 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
302 if (exGateway != null && exGateway.isEnableSnat()) {
daniel park576969a2018-03-09 07:07:41 +0900303 setSourceNat(osRouterIface, true);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900304 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900305 log.info("Connected subnet({}) to {}", osSubnet.getCidr(), osRouter.getName());
306 }
307
308 private void routerIfaceRemoved(Router osRouter, RouterInterface osRouterIface) {
Jian Liedc8b762018-03-22 15:42:00 +0900309 Subnet osSubnet = osNetworkAdminService.subnet(osRouterIface.getSubnetId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900310 if (osSubnet == null) {
311 final String error = String.format(
Jian Li71670d12018-03-02 21:31:07 +0900312 "Failed to set flows for router %s: subnet %s does not exist",
Hyunsun Moon44aac662017-02-18 02:07:01 +0900313 osRouterIface.getId(),
314 osRouterIface.getSubnetId());
315 throw new IllegalStateException(error);
316 }
317
Frank Wang245a6822017-06-14 09:51:35 +0800318 if (!osRouter.isAdminStateUp()) {
Jian Liedc8b762018-03-22 15:42:00 +0900319 Network network = osNetworkAdminService.network(osSubnet.getNetworkId());
SONA Project6bc5c4a2018-12-14 23:49:52 +0900320 Type netType = osNetworkAdminService.networkType(osSubnet.getNetworkId());
321 setRouterAdminRules(network.getProviderSegID(), netType, false);
Frank Wang245a6822017-06-14 09:51:35 +0800322 }
323
Hyunsun Moon44aac662017-02-18 02:07:01 +0900324 setInternalRoutes(osRouter, osSubnet, false);
Daniel Park51f9d1e2018-10-26 13:39:09 +0900325 setGatewayIcmp(osSubnet, osRouter, false);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900326 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
327 if (exGateway != null && exGateway.isEnableSnat()) {
daniel park576969a2018-03-09 07:07:41 +0900328 setSourceNat(osRouterIface, false);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900329 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900330 log.info("Disconnected subnet({}) from {}", osSubnet.getCidr(), osRouter.getName());
331 }
332
daniel park576969a2018-03-09 07:07:41 +0900333 private void setSourceNat(RouterInterface routerIface, boolean install) {
Jian Liedc8b762018-03-22 15:42:00 +0900334 Subnet osSubnet = osNetworkAdminService.subnet(routerIface.getSubnetId());
335 Network osNet = osNetworkAdminService.network(osSubnet.getNetworkId());
SONA Project6bc5c4a2018-12-14 23:49:52 +0900336 Type netType = osNetworkAdminService.networkType(osSubnet.getNetworkId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900337
Hyunsun Moon0d457362017-06-27 17:19:41 +0900338 osNodeService.completeNodes(COMPUTE).forEach(cNode -> {
339 setRulesToGateway(cNode, osNet.getProviderSegID(),
SONA Project6bc5c4a2018-12-14 23:49:52 +0900340 IpPrefix.valueOf(osSubnet.getCidr()), netType, install);
Hyunsun Moon0d457362017-06-27 17:19:41 +0900341 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900342
sanghoe765ce22017-06-23 17:54:57 +0900343 if (useStatefulSnat) {
344 setStatefulSnatRules(routerIface, install);
345 } else {
346 setReactiveSnatRules(routerIface, install);
347 }
348
349 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
350 log.info(updateStr + "external access for subnet({})", osSubnet.getCidr());
351 }
352
353 private void setStatefulSnatRules(RouterInterface routerIface, boolean install) {
Jian Liedc8b762018-03-22 15:42:00 +0900354 Subnet osSubnet = osNetworkAdminService.subnet(routerIface.getSubnetId());
355 Network osNet = osNetworkAdminService.network(osSubnet.getNetworkId());
SONA Project6bc5c4a2018-12-14 23:49:52 +0900356 Type netType = osNetworkAdminService.networkType(osSubnet.getNetworkId());
sanghoe765ce22017-06-23 17:54:57 +0900357
SONA Project6bc5c4a2018-12-14 23:49:52 +0900358 if (netType == FLAT) {
daniel park796c2eb2018-03-22 17:01:51 +0900359 return;
360 }
361
sanghoe765ce22017-06-23 17:54:57 +0900362 Optional<Router> osRouter = osRouterService.routers().stream()
363 .filter(router -> osRouterService.routerInterfaces(routerIface.getId()) != null)
364 .findAny();
365
366 if (!osRouter.isPresent()) {
367 log.error("Cannot find a router for router interface {} ", routerIface);
368 return;
369 }
370 IpAddress natAddress = getGatewayIpAddress(osRouter.get());
sangho072c4dd2017-05-17 10:45:21 +0900371 if (natAddress == null) {
372 return;
373 }
Jian Liedc8b762018-03-22 15:42:00 +0900374 String netId = osNetworkAdminService.subnet(routerIface.getSubnetId()).getNetworkId();
sangho072c4dd2017-05-17 10:45:21 +0900375
376 osNodeService.completeNodes(OpenstackNode.NodeType.GATEWAY)
377 .forEach(gwNode -> {
daniel park576969a2018-03-09 07:07:41 +0900378 instancePortService.instancePorts(netId)
Jian Lic2403592018-07-18 12:56:45 +0900379 .stream()
380 .filter(port -> port.state() == ACTIVE)
daniel park576969a2018-03-09 07:07:41 +0900381 .forEach(port -> setRulesForSnatIngressRule(gwNode.intgBridge(),
sangho072c4dd2017-05-17 10:45:21 +0900382 Long.parseLong(osNet.getProviderSegID()),
Jian Li4d138702018-11-27 17:25:28 +0900383 IpPrefix.valueOf(port.ipAddress(), VM_PREFIX),
sangho072c4dd2017-05-17 10:45:21 +0900384 port.deviceId(),
SONA Project6bc5c4a2018-12-14 23:49:52 +0900385 netType,
sangho072c4dd2017-05-17 10:45:21 +0900386 install));
387
388 setOvsNatIngressRule(gwNode.intgBridge(),
Jian Li4d138702018-11-27 17:25:28 +0900389 IpPrefix.valueOf(natAddress, VM_PREFIX),
sangho072c4dd2017-05-17 10:45:21 +0900390 Constants.DEFAULT_EXTERNAL_ROUTER_MAC, install);
391 setOvsNatEgressRule(gwNode.intgBridge(),
392 natAddress, Long.parseLong(osNet.getProviderSegID()),
393 gwNode.patchPortNum(), install);
394 });
sanghoe765ce22017-06-23 17:54:57 +0900395 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900396
sanghoe765ce22017-06-23 17:54:57 +0900397 private void setReactiveSnatRules(RouterInterface routerIface, boolean install) {
Jian Liedc8b762018-03-22 15:42:00 +0900398 Subnet osSubnet = osNetworkAdminService.subnet(routerIface.getSubnetId());
399 Network osNet = osNetworkAdminService.network(osSubnet.getNetworkId());
SONA Project6bc5c4a2018-12-14 23:49:52 +0900400 Type netType = osNetworkAdminService.networkType(osSubnet.getNetworkId());
sanghoe765ce22017-06-23 17:54:57 +0900401
402 osNodeService.completeNodes(GATEWAY)
403 .forEach(gwNode -> setRulesToController(
404 gwNode.intgBridge(),
405 osNet.getProviderSegID(),
406 IpPrefix.valueOf(osSubnet.getCidr()),
SONA Project6bc5c4a2018-12-14 23:49:52 +0900407 netType,
sanghoe765ce22017-06-23 17:54:57 +0900408 install));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900409 }
410
sangho072c4dd2017-05-17 10:45:21 +0900411 private IpAddress getGatewayIpAddress(Router osRouter) {
412
Daniel Park613ac372018-06-28 14:30:11 +0900413 if (osRouter.getExternalGatewayInfo() == null) {
414 return null;
415 }
Jian Li5ecfd1a2018-12-10 11:41:03 +0900416 String extNetId = osNetworkAdminService.network(
417 osRouter.getExternalGatewayInfo().getNetworkId()).getId();
Jian Liedc8b762018-03-22 15:42:00 +0900418 Optional<Subnet> extSubnet = osNetworkAdminService.subnets().stream()
sangho072c4dd2017-05-17 10:45:21 +0900419 .filter(subnet -> subnet.getNetworkId().equals(extNetId))
420 .findAny();
421
422 if (!extSubnet.isPresent()) {
423 log.error("Cannot find externel subnet for the router");
424 return null;
425 }
426
427 return IpAddress.valueOf(extSubnet.get().getGateway());
428 }
429
sanghoe765ce22017-06-23 17:54:57 +0900430 private void resetSnatRules() {
431 if (useStatefulSnat) {
432 osRouterService.routerInterfaces().forEach(
433 routerIface -> {
434 setReactiveSnatRules(routerIface, false);
435 setStatefulSnatRules(routerIface, true);
436 }
437 );
438 } else {
439 osRouterService.routerInterfaces().forEach(
440 routerIface -> {
441 setStatefulSnatRules(routerIface, false);
442 setReactiveSnatRules(routerIface, true);
443 }
444 );
445 }
446 }
447
Daniel Park51f9d1e2018-10-26 13:39:09 +0900448 private void setGatewayIcmp(Subnet osSubnet, Router osRouter, boolean install) {
Jian Li4d138702018-11-27 17:25:28 +0900449 OpenstackNode srcNatGw = osNodeService.completeNodes(GATEWAY)
450 .stream().findFirst().orElse(null);
daniel parkb5817102018-02-15 00:18:51 +0900451
Jian Li4d138702018-11-27 17:25:28 +0900452 if (srcNatGw == null) {
daniel parkb5817102018-02-15 00:18:51 +0900453 return;
454 }
455
Hyunsun Moon44aac662017-02-18 02:07:01 +0900456 if (Strings.isNullOrEmpty(osSubnet.getGateway())) {
457 // do nothing if no gateway is set
458 return;
459 }
460
461 // take ICMP request to a subnet gateway through gateway node group
Jian Li4d138702018-11-27 17:25:28 +0900462 Network net = osNetworkAdminService.network(osSubnet.getNetworkId());
Daniel Park51f9d1e2018-10-26 13:39:09 +0900463 Set<Subnet> routableSubnets = routableSubnets(osRouter, osSubnet.getId());
464
Jian Li4d138702018-11-27 17:25:28 +0900465 switch (net.getNetworkType()) {
daniel parkee8700b2017-05-11 15:50:03 +0900466 case VXLAN:
Jian Li4d138702018-11-27 17:25:28 +0900467 setGatewayIcmpForVxlan(osSubnet, srcNatGw, net, routableSubnets, install);
daniel parkee8700b2017-05-11 15:50:03 +0900468 break;
Jian Li2d68c192018-12-13 15:52:59 +0900469 case GRE:
470 setGatewayIcmpForGre(osSubnet, srcNatGw, net, routableSubnets, install);
471 break;
daniel parkee8700b2017-05-11 15:50:03 +0900472 case VLAN:
Jian Li4d138702018-11-27 17:25:28 +0900473 setGatewayIcmpForVlan(osSubnet, srcNatGw, net, routableSubnets, install);
daniel parkee8700b2017-05-11 15:50:03 +0900474 break;
475 default:
Jian Li4d138702018-11-27 17:25:28 +0900476 final String error = String.format("%s %s", ERR_UNSUPPORTED_NET_TYPE,
477 net.getNetworkType().toString());
daniel parkee8700b2017-05-11 15:50:03 +0900478 throw new IllegalStateException(error);
479 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900480
481 IpAddress gatewayIp = IpAddress.valueOf(osSubnet.getGateway());
daniel park576969a2018-03-09 07:07:41 +0900482 osNodeService.completeNodes(GATEWAY).forEach(gNode ->
Hyunsun Moon0d457362017-06-27 17:19:41 +0900483 setGatewayIcmpRule(
484 gatewayIp,
485 gNode.intgBridge(),
daniel park576969a2018-03-09 07:07:41 +0900486 install));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900487
488 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
489 log.debug(updateStr + "ICMP to {}", osSubnet.getGateway());
490 }
491
Jian Li4d138702018-11-27 17:25:28 +0900492 private void setGatewayIcmpForVxlan(Subnet osSubnet,
493 OpenstackNode srcNatGw,
494 Network network,
495 Set<Subnet> routableSubnets,
496 boolean install) {
497 osNodeService.completeNodes(COMPUTE).stream()
498 .filter(cNode -> cNode.dataIp() != null)
499 .forEach(cNode -> setRulesToGatewayWithRoutableSubnets(
500 cNode,
501 srcNatGw,
502 network.getProviderSegID(),
503 osSubnet,
504 routableSubnets,
SONA Project6bc5c4a2018-12-14 23:49:52 +0900505 Type.VXLAN,
Jian Li2d68c192018-12-13 15:52:59 +0900506 install));
507 }
508
509 private void setGatewayIcmpForGre(Subnet osSubnet,
510 OpenstackNode srcNatGw,
511 Network network,
512 Set<Subnet> routableSubnets,
513 boolean install) {
514 osNodeService.completeNodes(COMPUTE).stream()
515 .filter(cNode -> cNode.dataIp() != null)
516 .forEach(cNode -> setRulesToGatewayWithRoutableSubnets(
517 cNode,
518 srcNatGw,
519 network.getProviderSegID(),
520 osSubnet,
521 routableSubnets,
SONA Project6bc5c4a2018-12-14 23:49:52 +0900522 Type.GRE,
Jian Li4d138702018-11-27 17:25:28 +0900523 install));
524 }
525
526 private void setGatewayIcmpForVlan(Subnet osSubnet,
527 OpenstackNode srcNatGw,
528 Network network,
529 Set<Subnet> routableSubnets,
530 boolean install) {
531 osNodeService.completeNodes(COMPUTE).stream()
532 .filter(cNode -> cNode.vlanPortNum() != null)
533 .forEach(cNode -> setRulesToGatewayWithRoutableSubnets(
534 cNode,
535 srcNatGw,
536 network.getProviderSegID(),
537 osSubnet,
538 routableSubnets,
SONA Project6bc5c4a2018-12-14 23:49:52 +0900539 VLAN,
Jian Li4d138702018-11-27 17:25:28 +0900540 install));
541 }
542
Hyunsun Moon44aac662017-02-18 02:07:01 +0900543 private void setInternalRoutes(Router osRouter, Subnet updatedSubnet, boolean install) {
SONA Project6bc5c4a2018-12-14 23:49:52 +0900544 Type netType = osNetworkAdminService.networkType(updatedSubnet.getNetworkId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900545 Set<Subnet> routableSubnets = routableSubnets(osRouter, updatedSubnet.getId());
Jian Lib6969502018-10-30 20:38:07 +0900546 String updatedSegmentId = getSegmentId(updatedSubnet);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900547
548 // installs rule from/to my subnet intentionally to fix ICMP failure
549 // to my subnet gateway if no external gateway added to the router
Hyunsun Moon0d457362017-06-27 17:19:41 +0900550 osNodeService.completeNodes(COMPUTE).forEach(cNode -> {
551 setInternalRouterRules(
552 cNode.intgBridge(),
Jian Lib6969502018-10-30 20:38:07 +0900553 updatedSegmentId,
554 updatedSegmentId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900555 IpPrefix.valueOf(updatedSubnet.getCidr()),
556 IpPrefix.valueOf(updatedSubnet.getCidr()),
SONA Project6bc5c4a2018-12-14 23:49:52 +0900557 netType,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900558 install
559 );
Hyunsun Moon44aac662017-02-18 02:07:01 +0900560
Hyunsun Moon0d457362017-06-27 17:19:41 +0900561 routableSubnets.forEach(subnet -> {
562 setInternalRouterRules(
563 cNode.intgBridge(),
Jian Lib6969502018-10-30 20:38:07 +0900564 updatedSegmentId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900565 getSegmentId(subnet),
566 IpPrefix.valueOf(updatedSubnet.getCidr()),
567 IpPrefix.valueOf(subnet.getCidr()),
SONA Project6bc5c4a2018-12-14 23:49:52 +0900568 netType,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900569 install
570 );
571 setInternalRouterRules(
572 cNode.intgBridge(),
573 getSegmentId(subnet),
Jian Lib6969502018-10-30 20:38:07 +0900574 updatedSegmentId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900575 IpPrefix.valueOf(subnet.getCidr()),
576 IpPrefix.valueOf(updatedSubnet.getCidr()),
SONA Project6bc5c4a2018-12-14 23:49:52 +0900577 netType,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900578 install
579 );
580 });
581 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900582
daniel parkee8700b2017-05-11 15:50:03 +0900583
Hyunsun Moon44aac662017-02-18 02:07:01 +0900584 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
585 routableSubnets.forEach(subnet -> log.debug(
586 updateStr + "route between subnet:{} and subnet:{}",
587 subnet.getCidr(),
588 updatedSubnet.getCidr()));
589 }
590
591 private Set<Subnet> routableSubnets(Router osRouter, String osSubnetId) {
592 Set<Subnet> osSubnets = osRouterService.routerInterfaces(osRouter.getId())
593 .stream()
594 .filter(iface -> !Objects.equals(iface.getSubnetId(), osSubnetId))
Jian Liedc8b762018-03-22 15:42:00 +0900595 .map(iface -> osNetworkAdminService.subnet(iface.getSubnetId()))
Hyunsun Moon44aac662017-02-18 02:07:01 +0900596 .collect(Collectors.toSet());
597 return ImmutableSet.copyOf(osSubnets);
598 }
599
daniel parkee8700b2017-05-11 15:50:03 +0900600 private String getSegmentId(Subnet osSubnet) {
Jian Liedc8b762018-03-22 15:42:00 +0900601 return osNetworkAdminService.network(osSubnet.getNetworkId()).getProviderSegID();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900602 }
603
604 private void setGatewayIcmpRule(IpAddress gatewayIp, DeviceId deviceId, boolean install) {
605 TrafficSelector selector = DefaultTrafficSelector.builder()
606 .matchEthType(Ethernet.TYPE_IPV4)
607 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900608 .matchIPDst(gatewayIp.getIp4Address().toIpPrefix())
Hyunsun Moon44aac662017-02-18 02:07:01 +0900609 .build();
610
611 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Jian Li4d5c5c32018-04-02 16:38:18 +0900612 .punt()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900613 .build();
614
sanghodc375372017-06-08 10:41:30 +0900615 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900616 appId,
617 deviceId,
618 selector,
619 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900620 PRIORITY_ICMP_RULE,
sanghodc375372017-06-08 10:41:30 +0900621 Constants.GW_COMMON_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900622 install);
623 }
624
Jian Li4d138702018-11-27 17:25:28 +0900625 private void setInternalRouterRules(DeviceId deviceId, String srcSegId, String dstSegId,
daniel parkee8700b2017-05-11 15:50:03 +0900626 IpPrefix srcSubnet, IpPrefix dstSubnet,
SONA Project6bc5c4a2018-12-14 23:49:52 +0900627 Type networkType, boolean install) {
Jian Li4d138702018-11-27 17:25:28 +0900628
daniel parkee8700b2017-05-11 15:50:03 +0900629 switch (networkType) {
630 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900631 case GRE:
632 setInternalRouterRulesForTunnel(deviceId, srcSegId, dstSegId,
Jian Li4d138702018-11-27 17:25:28 +0900633 srcSubnet, dstSubnet, install);
daniel parkee8700b2017-05-11 15:50:03 +0900634 break;
635 case VLAN:
Jian Li4d138702018-11-27 17:25:28 +0900636 setInternalRouterRulesForVlan(deviceId, srcSegId, dstSegId,
637 srcSubnet, dstSubnet, install);
daniel parkee8700b2017-05-11 15:50:03 +0900638 break;
639 default:
Jian Li4d138702018-11-27 17:25:28 +0900640 final String error = String.format("%s %s", ERR_UNSUPPORTED_NET_TYPE,
641 networkType.toString());
daniel parkee8700b2017-05-11 15:50:03 +0900642 throw new IllegalStateException(error);
643 }
644
Hyunsun Moon44aac662017-02-18 02:07:01 +0900645 }
646
Jian Li2d68c192018-12-13 15:52:59 +0900647 private void setInternalRouterRulesForTunnel(DeviceId deviceId,
648 String srcSegmentId,
649 String dstSegmentId,
650 IpPrefix srcSubnet,
651 IpPrefix dstSubnet,
652 boolean install) {
Jian Li4d138702018-11-27 17:25:28 +0900653 TrafficSelector selector;
654 TrafficTreatment treatment;
655 selector = DefaultTrafficSelector.builder()
656 .matchEthType(Ethernet.TYPE_IPV4)
657 .matchTunnelId(Long.parseLong(srcSegmentId))
658 .matchIPSrc(srcSubnet.getIp4Prefix())
659 .matchIPDst(dstSubnet.getIp4Prefix())
660 .build();
661
662 treatment = DefaultTrafficTreatment.builder()
663 .setTunnelId(Long.parseLong(dstSegmentId))
664 .transition(STAT_OUTBOUND_TABLE)
665 .build();
666
667 osFlowRuleService.setRule(
668 appId,
669 deviceId,
670 selector,
671 treatment,
672 PRIORITY_INTERNAL_ROUTING_RULE,
673 ROUTING_TABLE,
674 install);
675
676 selector = DefaultTrafficSelector.builder()
677 .matchEthType(Ethernet.TYPE_IPV4)
678 .matchTunnelId(Long.parseLong(dstSegmentId))
679 .matchIPSrc(srcSubnet.getIp4Prefix())
680 .matchIPDst(dstSubnet.getIp4Prefix())
681 .build();
682
683 treatment = DefaultTrafficTreatment.builder()
684 .setTunnelId(Long.parseLong(dstSegmentId))
685 .transition(STAT_OUTBOUND_TABLE)
686 .build();
687
688 osFlowRuleService.setRule(
689 appId,
690 deviceId,
691 selector,
692 treatment,
693 PRIORITY_INTERNAL_ROUTING_RULE,
694 ROUTING_TABLE,
695 install);
696 }
697
698 private void setInternalRouterRulesForVlan(DeviceId deviceId,
699 String srcSegmentId,
700 String dstSegmentId,
701 IpPrefix srcSubnet,
702 IpPrefix dstSubnet,
703 boolean install) {
704 TrafficSelector selector;
705 TrafficTreatment treatment;
706 selector = DefaultTrafficSelector.builder()
707 .matchEthType(Ethernet.TYPE_IPV4)
708 .matchVlanId(VlanId.vlanId(srcSegmentId))
709 .matchIPSrc(srcSubnet.getIp4Prefix())
710 .matchIPDst(dstSubnet.getIp4Prefix())
711 .build();
712
713 treatment = DefaultTrafficTreatment.builder()
714 .setVlanId(VlanId.vlanId(dstSegmentId))
715 .transition(STAT_OUTBOUND_TABLE)
716 .build();
717
718 osFlowRuleService.setRule(
719 appId,
720 deviceId,
721 selector,
722 treatment,
723 PRIORITY_INTERNAL_ROUTING_RULE,
724 ROUTING_TABLE,
725 install);
726
727 selector = DefaultTrafficSelector.builder()
728 .matchEthType(Ethernet.TYPE_IPV4)
729 .matchVlanId(VlanId.vlanId(dstSegmentId))
730 .matchIPSrc(srcSubnet.getIp4Prefix())
731 .matchIPDst(dstSubnet.getIp4Prefix())
732 .build();
733
734 treatment = DefaultTrafficTreatment.builder()
735 .setVlanId(VlanId.vlanId(dstSegmentId))
736 .transition(STAT_OUTBOUND_TABLE)
737 .build();
738
739 osFlowRuleService.setRule(
740 appId,
741 deviceId,
742 selector,
743 treatment,
744 PRIORITY_INTERNAL_ROUTING_RULE,
745 ROUTING_TABLE,
746 install);
747 }
748
Jian Li5ecfd1a2018-12-10 11:41:03 +0900749 private void setRulesToGateway(OpenstackNode osNode,
750 String segmentId,
751 IpPrefix srcSubnet,
SONA Project6bc5c4a2018-12-14 23:49:52 +0900752 Type networkType,
Jian Li5ecfd1a2018-12-10 11:41:03 +0900753 boolean install) {
754 OpenstackNode sourceNatGateway =
755 osNodeService.completeNodes(GATEWAY).stream().findFirst().orElse(null);
daniel parkb5817102018-02-15 00:18:51 +0900756
757 if (sourceNatGateway == null) {
758 return;
759 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900760
daniel parkee8700b2017-05-11 15:50:03 +0900761 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
762 .matchEthType(Ethernet.TYPE_IPV4)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900763 .matchIPSrc(srcSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900764 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
765
766 switch (networkType) {
767 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900768 case GRE:
daniel parkee8700b2017-05-11 15:50:03 +0900769 sBuilder.matchTunnelId(Long.parseLong(segmentId));
daniel parkee8700b2017-05-11 15:50:03 +0900770 break;
771 case VLAN:
772 sBuilder.matchVlanId(VlanId.vlanId(segmentId));
daniel parkee8700b2017-05-11 15:50:03 +0900773 break;
774 default:
Jian Li71670d12018-03-02 21:31:07 +0900775 final String error = String.format("%s %s",
776 ERR_UNSUPPORTED_NET_TYPE,
daniel parkee8700b2017-05-11 15:50:03 +0900777 networkType.toString());
778 throw new IllegalStateException(error);
779 }
780
Daniel Parkc64b4c62018-05-09 18:13:39 +0900781 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
782
783 switch (networkType) {
784 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900785 case GRE:
SONA Project6bc5c4a2018-12-14 23:49:52 +0900786 PortNumber portNum = tunnelPortNumByNetType(networkType, osNode);
Daniel Parkc64b4c62018-05-09 18:13:39 +0900787 tBuilder.extension(buildExtension(
788 deviceService,
789 osNode.intgBridge(),
790 sourceNatGateway.dataIp().getIp4Address()),
791 osNode.intgBridge())
Jian Li2d68c192018-12-13 15:52:59 +0900792 .setOutput(portNum);
Daniel Parkc64b4c62018-05-09 18:13:39 +0900793 break;
794
795 case VLAN:
796 tBuilder.setOutput(osNode.vlanPortNum());
797 break;
798
799 default:
800 break;
801 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900802
sanghodc375372017-06-08 10:41:30 +0900803 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900804 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900805 osNode.intgBridge(),
daniel parkee8700b2017-05-11 15:50:03 +0900806 sBuilder.build(),
Daniel Parkc64b4c62018-05-09 18:13:39 +0900807 tBuilder.build(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900808 PRIORITY_EXTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900809 ROUTING_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900810 install);
811 }
812
Jian Li5ecfd1a2018-12-10 11:41:03 +0900813 private void setRulesForSnatIngressRule(DeviceId deviceId,
814 Long vni,
815 IpPrefix destVmIp,
816 DeviceId dstDeviceId,
SONA Project6bc5c4a2018-12-14 23:49:52 +0900817 Type networkType,
Jian Li5ecfd1a2018-12-10 11:41:03 +0900818 boolean install) {
sangho072c4dd2017-05-17 10:45:21 +0900819
820 TrafficSelector selector = DefaultTrafficSelector.builder()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900821 .matchEthType(Ethernet.TYPE_IPV4)
sangho072c4dd2017-05-17 10:45:21 +0900822 .matchIPDst(destVmIp)
823 .build();
Hyunsun Moon0d457362017-06-27 17:19:41 +0900824
SONA Project6bc5c4a2018-12-14 23:49:52 +0900825 PortNumber portNum = tunnelPortNumByNetType(networkType,
Jian Li2d68c192018-12-13 15:52:59 +0900826 osNodeService.node(deviceId));
827
sangho072c4dd2017-05-17 10:45:21 +0900828 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
829 .setTunnelId(vni)
830 .extension(buildExtension(
831 deviceService,
832 deviceId,
833 osNodeService.node(dstDeviceId).dataIp().getIp4Address()),
834 deviceId)
Jian Li2d68c192018-12-13 15:52:59 +0900835 .setOutput(portNum)
sangho072c4dd2017-05-17 10:45:21 +0900836 .build();
daniel parkee8700b2017-05-11 15:50:03 +0900837
sanghodc375372017-06-08 10:41:30 +0900838 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900839 appId,
sangho072c4dd2017-05-17 10:45:21 +0900840 deviceId,
841 selector,
842 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900843 PRIORITY_EXTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900844 Constants.GW_COMMON_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900845 install);
846 }
847
Jian Li5ecfd1a2018-12-10 11:41:03 +0900848 private void setRulesToGatewayWithRoutableSubnets(OpenstackNode osNode,
849 OpenstackNode sourceNatGateway,
850 String segmentId,
851 Subnet updatedSubnet,
852 Set<Subnet> routableSubnets,
SONA Project6bc5c4a2018-12-14 23:49:52 +0900853 Type networkType,
Daniel Park51f9d1e2018-10-26 13:39:09 +0900854 boolean install) {
855 //At first we install flow rules to gateway with segId and gatewayIp of updated subnet
Jian Li5ecfd1a2018-12-10 11:41:03 +0900856 setRulesToGatewayWithDstIp(osNode, sourceNatGateway, segmentId,
Jian Li2d68c192018-12-13 15:52:59 +0900857 IpAddress.valueOf(updatedSubnet.getGateway()), networkType, install);
Daniel Park51f9d1e2018-10-26 13:39:09 +0900858
859 routableSubnets.forEach(subnet -> {
860 setRulesToGatewayWithDstIp(osNode, sourceNatGateway,
861 segmentId, IpAddress.valueOf(subnet.getGateway()),
Jian Li2d68c192018-12-13 15:52:59 +0900862 networkType, install);
Daniel Park51f9d1e2018-10-26 13:39:09 +0900863
864 Network network = osNetworkAdminService.network(subnet.getNetworkId());
865 setRulesToGatewayWithDstIp(osNode, sourceNatGateway,
866 network.getProviderSegID(), IpAddress.valueOf(updatedSubnet.getGateway()),
Jian Li2d68c192018-12-13 15:52:59 +0900867 networkType, install);
Daniel Park51f9d1e2018-10-26 13:39:09 +0900868 });
869 }
870
Jian Li5ecfd1a2018-12-10 11:41:03 +0900871 private void setRulesToGatewayWithDstIp(OpenstackNode osNode,
872 OpenstackNode sourceNatGateway,
873 String segmentId,
874 IpAddress dstIp,
SONA Project6bc5c4a2018-12-14 23:49:52 +0900875 Type networkType,
Jian Li5ecfd1a2018-12-10 11:41:03 +0900876 boolean install) {
Daniel Parkc64b4c62018-05-09 18:13:39 +0900877 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
878 .matchEthType(Ethernet.TYPE_IPV4)
879 .matchIPDst(dstIp.getIp4Address().toIpPrefix());
880
Daniel Parkc64b4c62018-05-09 18:13:39 +0900881 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
882
Jian Li2d68c192018-12-13 15:52:59 +0900883 switch (networkType) {
Daniel Parkc64b4c62018-05-09 18:13:39 +0900884 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900885 case GRE:
Daniel Park51f9d1e2018-10-26 13:39:09 +0900886 sBuilder.matchTunnelId(Long.parseLong(segmentId));
Jian Li2d68c192018-12-13 15:52:59 +0900887
SONA Project6bc5c4a2018-12-14 23:49:52 +0900888 PortNumber portNum = tunnelPortNumByNetType(networkType, osNode);
Jian Li2d68c192018-12-13 15:52:59 +0900889
Daniel Parkc64b4c62018-05-09 18:13:39 +0900890 tBuilder.extension(buildExtension(
daniel parkb5817102018-02-15 00:18:51 +0900891 deviceService,
892 osNode.intgBridge(),
893 sourceNatGateway.dataIp().getIp4Address()),
894 osNode.intgBridge())
Jian Li2d68c192018-12-13 15:52:59 +0900895 .setOutput(portNum);
Daniel Parkc64b4c62018-05-09 18:13:39 +0900896 break;
Daniel Parkc64b4c62018-05-09 18:13:39 +0900897 case VLAN:
Daniel Park51f9d1e2018-10-26 13:39:09 +0900898 sBuilder.matchVlanId(VlanId.vlanId(segmentId));
Daniel Parkc64b4c62018-05-09 18:13:39 +0900899 tBuilder.setOutput(osNode.vlanPortNum());
900 break;
901
902 default:
903 break;
904 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900905
sanghodc375372017-06-08 10:41:30 +0900906 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900907 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900908 osNode.intgBridge(),
Daniel Parkc64b4c62018-05-09 18:13:39 +0900909 sBuilder.build(),
910 tBuilder.build(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900911 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900912 ROUTING_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900913 install);
914 }
915
Jian Li5ecfd1a2018-12-10 11:41:03 +0900916 private void setOvsNatIngressRule(DeviceId deviceId,
917 IpPrefix cidr,
918 MacAddress dstMac,
919 boolean install) {
sangho072c4dd2017-05-17 10:45:21 +0900920
921 TrafficSelector selector = DefaultTrafficSelector.builder()
922 .matchEthType(Ethernet.TYPE_IPV4)
923 .matchIPDst(cidr)
924 .build();
925
Jian Liedc8b762018-03-22 15:42:00 +0900926 ExtensionTreatment natTreatment = RulePopulatorUtil
927 .niciraConnTrackTreatmentBuilder(driverService, deviceId)
sangho072c4dd2017-05-17 10:45:21 +0900928 .commit(false)
929 .natAction(true)
930 .table((short) 0)
931 .build();
932
933 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
934 .setEthDst(dstMac)
935 .extension(natTreatment, deviceId)
936 .build();
937
938 osFlowRuleService.setRule(
939 appId,
940 deviceId,
941 selector,
942 treatment,
sanghoe765ce22017-06-23 17:54:57 +0900943 PRIORITY_STATEFUL_SNAT_RULE,
sangho072c4dd2017-05-17 10:45:21 +0900944 GW_COMMON_TABLE,
945 install);
946 }
947
Jian Li5ecfd1a2018-12-10 11:41:03 +0900948 private void setOvsNatEgressRule(DeviceId deviceId,
949 IpAddress natAddress,
950 long vni,
951 PortNumber output,
sangho072c4dd2017-05-17 10:45:21 +0900952 boolean install) {
953
954 TrafficSelector selector = DefaultTrafficSelector.builder()
955 .matchEthType(Ethernet.TYPE_IPV4)
956 .matchEthDst(DEFAULT_GATEWAY_MAC)
957 .matchTunnelId(vni)
958 .build();
959
Jian Liedc8b762018-03-22 15:42:00 +0900960 ExtensionTreatment natTreatment = RulePopulatorUtil
961 .niciraConnTrackTreatmentBuilder(driverService, deviceId)
sangho072c4dd2017-05-17 10:45:21 +0900962 .commit(true)
963 .natAction(true)
964 .natIp(natAddress)
965 .build();
966
967 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
968 .extension(natTreatment, deviceId)
969 .setEthDst(DEFAULT_EXTERNAL_ROUTER_MAC)
970 .setEthSrc(DEFAULT_GATEWAY_MAC)
971 .setOutput(output)
972 .build();
973
974 osFlowRuleService.setRule(
975 appId,
976 deviceId,
977 selector,
978 treatment,
sanghoe765ce22017-06-23 17:54:57 +0900979 PRIORITY_STATEFUL_SNAT_RULE,
sangho072c4dd2017-05-17 10:45:21 +0900980 GW_COMMON_TABLE,
981 install);
982 }
983
Jian Li5ecfd1a2018-12-10 11:41:03 +0900984 private void setRulesToController(DeviceId deviceId,
985 String segmentId,
986 IpPrefix srcSubnet,
SONA Project6bc5c4a2018-12-14 23:49:52 +0900987 Type networkType,
Jian Li5ecfd1a2018-12-10 11:41:03 +0900988 boolean install) {
sanghoe765ce22017-06-23 17:54:57 +0900989 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
990 .matchEthType(Ethernet.TYPE_IPV4)
Daniel Parkc64b4c62018-05-09 18:13:39 +0900991 .matchIPSrc(srcSubnet)
992 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
993
sanghoe765ce22017-06-23 17:54:57 +0900994 switch (networkType) {
995 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +0900996 case GRE:
Daniel Parkc64b4c62018-05-09 18:13:39 +0900997 sBuilder.matchTunnelId(Long.parseLong(segmentId));
sanghoe765ce22017-06-23 17:54:57 +0900998 break;
999 case VLAN:
Daniel Parkc64b4c62018-05-09 18:13:39 +09001000 sBuilder.matchVlanId(VlanId.vlanId(segmentId));
sanghoe765ce22017-06-23 17:54:57 +09001001 break;
1002 default:
Jian Li71670d12018-03-02 21:31:07 +09001003 final String error = String.format("%s %s",
1004 ERR_UNSUPPORTED_NET_TYPE,
sanghoe765ce22017-06-23 17:54:57 +09001005 networkType.toString());
1006 throw new IllegalStateException(error);
1007 }
1008
Daniel Parkc64b4c62018-05-09 18:13:39 +09001009 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
sanghoe765ce22017-06-23 17:54:57 +09001010
SONA Project6bc5c4a2018-12-14 23:49:52 +09001011 if (networkType == VLAN) {
sanghoe765ce22017-06-23 17:54:57 +09001012 tBuilder.popVlan();
1013 }
1014
Jian Li4d5c5c32018-04-02 16:38:18 +09001015 tBuilder.punt();
sanghoe765ce22017-06-23 17:54:57 +09001016
1017 osFlowRuleService.setRule(
1018 appId,
1019 deviceId,
1020 sBuilder.build(),
1021 tBuilder.build(),
1022 PRIORITY_EXTERNAL_ROUTING_RULE,
1023 GW_COMMON_TABLE,
1024 install);
sanghoe765ce22017-06-23 17:54:57 +09001025 }
sangho072c4dd2017-05-17 10:45:21 +09001026
Jian Li5ecfd1a2018-12-10 11:41:03 +09001027 private void setRouterAdminRules(String segmentId,
SONA Project6bc5c4a2018-12-14 23:49:52 +09001028 Type networkType,
Jian Li5ecfd1a2018-12-10 11:41:03 +09001029 boolean install) {
Frank Wang245a6822017-06-14 09:51:35 +08001030 TrafficTreatment treatment;
1031 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
1032 .matchEthType(Ethernet.TYPE_IPV4);
1033
1034 switch (networkType) {
1035 case VXLAN:
Jian Li2d68c192018-12-13 15:52:59 +09001036 case GRE:
Frank Wang245a6822017-06-14 09:51:35 +08001037 sBuilder.matchTunnelId(Long.parseLong(segmentId));
1038 break;
1039 case VLAN:
1040 sBuilder.matchVlanId(VlanId.vlanId(segmentId));
1041 break;
1042 default:
Jian Li71670d12018-03-02 21:31:07 +09001043 final String error = String.format("%s %s",
1044 ERR_UNSUPPORTED_NET_TYPE,
Frank Wang245a6822017-06-14 09:51:35 +08001045 networkType.toString());
1046 throw new IllegalStateException(error);
1047 }
1048
1049 treatment = DefaultTrafficTreatment.builder()
1050 .drop()
1051 .build();
1052
1053 osNodeService.completeNodes().stream()
1054 .filter(osNode -> osNode.type() == COMPUTE)
1055 .forEach(osNode -> {
1056 osFlowRuleService.setRule(
1057 appId,
1058 osNode.intgBridge(),
1059 sBuilder.build(),
1060 treatment,
1061 PRIORITY_ADMIN_RULE,
1062 ROUTING_TABLE,
1063 install);
1064 });
1065 }
1066
Hyunsun Moon44aac662017-02-18 02:07:01 +09001067 private class InternalRouterEventListener implements OpenstackRouterListener {
1068
Jian Li34220ea2018-11-14 01:30:24 +09001069 private boolean isRelevantHelper() {
1070 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001071 }
1072
1073 // FIXME only one leader in the cluster should process
1074 @Override
1075 public void event(OpenstackRouterEvent event) {
1076 switch (event.type()) {
1077 case OPENSTACK_ROUTER_CREATED:
Jian Li4d138702018-11-27 17:25:28 +09001078 eventExecutor.execute(() -> processRouterCreation(event));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001079 break;
1080 case OPENSTACK_ROUTER_UPDATED:
Jian Li4d138702018-11-27 17:25:28 +09001081 eventExecutor.execute(() -> processRouterUpdate(event));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001082 break;
1083 case OPENSTACK_ROUTER_REMOVED:
Jian Li4d138702018-11-27 17:25:28 +09001084 eventExecutor.execute(() -> processRouterRemoval(event));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001085 break;
1086 case OPENSTACK_ROUTER_INTERFACE_ADDED:
Jian Li4d138702018-11-27 17:25:28 +09001087 eventExecutor.execute(() -> processRouterIntfCreation(event));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001088 break;
1089 case OPENSTACK_ROUTER_INTERFACE_UPDATED:
Jian Li4d138702018-11-27 17:25:28 +09001090 eventExecutor.execute(() -> processRouterIntfUpdate(event));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001091 break;
1092 case OPENSTACK_ROUTER_INTERFACE_REMOVED:
Jian Li4d138702018-11-27 17:25:28 +09001093 eventExecutor.execute(() -> processRouterIntfRemoval(event));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001094 break;
1095 case OPENSTACK_ROUTER_GATEWAY_ADDED:
Jian Li32b03622018-11-06 17:54:24 +09001096 log.debug("Router external gateway {} added",
1097 event.externalGateway().getNetworkId());
Ray Milkey08932a72018-02-20 15:34:38 -08001098 break;
Hyunsun Moon44aac662017-02-18 02:07:01 +09001099 case OPENSTACK_ROUTER_GATEWAY_REMOVED:
Jian Li32b03622018-11-06 17:54:24 +09001100 log.debug("Router external gateway {} removed",
1101 event.externalGateway().getNetworkId());
Ray Milkey08932a72018-02-20 15:34:38 -08001102 break;
Hyunsun Moon44aac662017-02-18 02:07:01 +09001103 case OPENSTACK_FLOATING_IP_CREATED:
1104 case OPENSTACK_FLOATING_IP_UPDATED:
1105 case OPENSTACK_FLOATING_IP_REMOVED:
1106 case OPENSTACK_FLOATING_IP_ASSOCIATED:
1107 case OPENSTACK_FLOATING_IP_DISASSOCIATED:
1108 default:
1109 // do nothing for the other events
1110 break;
1111 }
1112 }
Jian Li4d138702018-11-27 17:25:28 +09001113
1114 private void processRouterCreation(OpenstackRouterEvent event) {
1115 if (!isRelevantHelper()) {
1116 return;
1117 }
1118
1119 log.debug("Router(name:{}, ID:{}) is created",
1120 event.subject().getName(),
1121 event.subject().getId());
1122
1123 routerUpdated(event.subject());
1124 }
1125
1126 private void processRouterUpdate(OpenstackRouterEvent event) {
1127 if (!isRelevantHelper()) {
1128 return;
1129 }
1130
1131 log.debug("Router(name:{}, ID:{}) is updated",
1132 event.subject().getName(),
1133 event.subject().getId());
1134
1135 routerUpdated(event.subject());
1136 }
1137
1138 private void processRouterRemoval(OpenstackRouterEvent event) {
1139 if (!isRelevantHelper()) {
1140 return;
1141 }
1142
1143 log.debug("Router(name:{}, ID:{}) is removed",
1144 event.subject().getName(),
1145 event.subject().getId());
1146
1147 routerRemove(event.subject());
1148 }
1149
1150 private void processRouterIntfCreation(OpenstackRouterEvent event) {
1151 if (!isRelevantHelper()) {
1152 return;
1153 }
1154
1155 log.debug("Router interface {} added to router {}",
1156 event.routerIface().getPortId(),
1157 event.routerIface().getId());
1158
1159 routerIfaceAdded(event.subject(), event.routerIface());
1160 }
1161
1162 private void processRouterIntfUpdate(OpenstackRouterEvent event) {
1163 log.debug("Router interface {} on {} updated",
1164 event.routerIface().getPortId(),
1165 event.routerIface().getId());
1166 }
1167
1168 private void processRouterIntfRemoval(OpenstackRouterEvent event) {
1169 if (!isRelevantHelper()) {
1170 return;
1171 }
1172
1173 log.debug("Router interface {} removed from router {}",
1174 event.routerIface().getPortId(),
1175 event.routerIface().getId());
1176
1177 routerIfaceRemoved(event.subject(), event.routerIface());
1178 }
Hyunsun Moon44aac662017-02-18 02:07:01 +09001179 }
1180
1181 private class InternalNodeEventListener implements OpenstackNodeListener {
1182
Jian Li34220ea2018-11-14 01:30:24 +09001183 private boolean isRelevantHelper() {
1184 return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
Hyunsun Moon44aac662017-02-18 02:07:01 +09001185 }
1186
1187 @Override
1188 public void event(OpenstackNodeEvent event) {
1189 OpenstackNode osNode = event.subject();
Hyunsun Moon44aac662017-02-18 02:07:01 +09001190 switch (event.type()) {
Hyunsun Moon0d457362017-06-27 17:19:41 +09001191 case OPENSTACK_NODE_COMPLETE:
1192 case OPENSTACK_NODE_INCOMPLETE:
Daniel Park6ed9cf02018-06-27 19:07:44 +09001193 case OPENSTACK_NODE_UPDATED:
1194 case OPENSTACK_NODE_REMOVED:
Hyunsun Moon44aac662017-02-18 02:07:01 +09001195 eventExecutor.execute(() -> {
Jian Li34220ea2018-11-14 01:30:24 +09001196 if (!isRelevantHelper()) {
1197 return;
1198 }
Jian Li4d138702018-11-27 17:25:28 +09001199 reconfigureRouters(osNode);
Hyunsun Moon44aac662017-02-18 02:07:01 +09001200 });
1201 break;
Hyunsun Moon0d457362017-06-27 17:19:41 +09001202 case OPENSTACK_NODE_CREATED:
Hyunsun Moon44aac662017-02-18 02:07:01 +09001203 default:
1204 break;
1205 }
1206 }
1207
Jian Li4d138702018-11-27 17:25:28 +09001208 private void reconfigureRouters(OpenstackNode osNode) {
Hyunsun Moon44aac662017-02-18 02:07:01 +09001209 osRouterService.routers().forEach(osRouter -> {
1210 routerUpdated(osRouter);
1211 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
1212 routerIfaceAdded(osRouter, iface);
1213 });
1214 });
Jian Li4d138702018-11-27 17:25:28 +09001215 log.info("Reconfigure routers for {}", osNode.hostname());
Hyunsun Moon44aac662017-02-18 02:07:01 +09001216 }
1217 }
sangho072c4dd2017-05-17 10:45:21 +09001218
1219 private class InternalInstancePortListener implements InstancePortListener {
1220
Jian Li34220ea2018-11-14 01:30:24 +09001221 private boolean isRelevantHelper(InstancePortEvent event) {
1222 return mastershipService.isLocalMaster(event.subject().deviceId());
sangho072c4dd2017-05-17 10:45:21 +09001223 }
1224
1225 @Override
1226 public void event(InstancePortEvent event) {
1227 InstancePort instPort = event.subject();
1228 switch (event.type()) {
sangho072c4dd2017-05-17 10:45:21 +09001229 case OPENSTACK_INSTANCE_PORT_DETECTED:
Jian Liec5c32b2018-07-13 14:28:58 +09001230 case OPENSTACK_INSTANCE_PORT_UPDATED:
Jian Li4d138702018-11-27 17:25:28 +09001231 eventExecutor.execute(() ->
1232 processInstancePortDetection(event, instPort));
sangho072c4dd2017-05-17 10:45:21 +09001233 break;
1234 case OPENSTACK_INSTANCE_PORT_VANISHED:
Jian Li4d138702018-11-27 17:25:28 +09001235 eventExecutor.execute(() ->
1236 processInstancePortRemoval(event, instPort));
Jian Liec5c32b2018-07-13 14:28:58 +09001237 break;
1238 case OPENSTACK_INSTANCE_MIGRATION_STARTED:
Jian Li4d138702018-11-27 17:25:28 +09001239 eventExecutor.execute(() ->
1240 processInstanceMigrationStart(event, instPort));
sangho072c4dd2017-05-17 10:45:21 +09001241 break;
Jian Li24ec59f2018-05-23 19:01:25 +09001242 case OPENSTACK_INSTANCE_MIGRATION_ENDED:
Jian Li4d138702018-11-27 17:25:28 +09001243 eventExecutor.execute(() ->
1244 processInstanceMigrationEnd(event, instPort));
Jian Li24ec59f2018-05-23 19:01:25 +09001245 break;
sangho072c4dd2017-05-17 10:45:21 +09001246 default:
1247 break;
1248 }
1249 }
1250
Jian Li4d138702018-11-27 17:25:28 +09001251 private void processInstancePortDetection(InstancePortEvent event,
1252 InstancePort instPort) {
1253 if (!isRelevantHelper(event)) {
1254 return;
1255 }
1256
1257 log.info("RoutingHandler: Instance port detected MAC:{} IP:{}",
1258 instPort.macAddress(),
1259 instPort.ipAddress());
1260
1261 instPortDetected(event.subject());
1262 }
1263
1264 private void processInstancePortRemoval(InstancePortEvent event,
1265 InstancePort instPort) {
1266 if (!isRelevantHelper(event)) {
1267 return;
1268 }
1269
1270 log.info("RoutingHandler: Instance port vanished MAC:{} IP:{}",
1271 instPort.macAddress(),
1272 instPort.ipAddress());
1273
1274 instPortRemoved(event.subject());
1275 }
1276
1277 private void processInstanceMigrationStart(InstancePortEvent event,
1278 InstancePort instPort) {
1279 if (!isRelevantHelper(event)) {
1280 return;
1281 }
1282
1283 log.info("RoutingHandler: Migration started for MAC:{} IP:{}",
1284 instPort.macAddress(),
1285 instPort.ipAddress());
1286
1287 instPortDetected(instPort);
1288 }
1289
1290 private void processInstanceMigrationEnd(InstancePortEvent event,
1291 InstancePort instPort) {
1292 log.info("RoutingHandler: Migration finished for MAC:{} IP:{}",
1293 instPort.macAddress(),
1294 instPort.ipAddress());
1295 // TODO: need to reconfigure rules to point to update VM
1296 }
1297
sangho072c4dd2017-05-17 10:45:21 +09001298 private void instPortDetected(InstancePort instPort) {
Jian Li4d138702018-11-27 17:25:28 +09001299 Network network = osNetworkAdminService.network(instPort.networkId());
SONA Project6bc5c4a2018-12-14 23:49:52 +09001300 Type netType = osNetworkAdminService.networkType(instPort.networkId());
1301
1302 if (netType == FLAT) {
daniel park796c2eb2018-03-22 17:01:51 +09001303 return;
1304 }
Daniel Parkc64b4c62018-05-09 18:13:39 +09001305
1306 if (useStatefulSnat) {
1307 osNodeService.completeNodes(GATEWAY)
1308 .forEach(gwNode -> setRulesForSnatIngressRule(
1309 gwNode.intgBridge(),
Jian Li4d138702018-11-27 17:25:28 +09001310 Long.parseLong(network.getProviderSegID()),
1311 IpPrefix.valueOf(instPort.ipAddress(), VM_PREFIX),
SONA Project6bc5c4a2018-12-14 23:49:52 +09001312 instPort.deviceId(), netType, true));
Daniel Parkc64b4c62018-05-09 18:13:39 +09001313 }
sangho072c4dd2017-05-17 10:45:21 +09001314 }
1315
1316 private void instPortRemoved(InstancePort instPort) {
Jian Li4d138702018-11-27 17:25:28 +09001317 Network network = osNetworkAdminService.network(instPort.networkId());
SONA Project6bc5c4a2018-12-14 23:49:52 +09001318 Type netType = osNetworkAdminService.networkType(instPort.networkId());
1319
1320 if (netType == FLAT) {
daniel park796c2eb2018-03-22 17:01:51 +09001321 return;
1322 }
Daniel Parkc64b4c62018-05-09 18:13:39 +09001323
1324 if (useStatefulSnat) {
1325 osNodeService.completeNodes(GATEWAY)
1326 .forEach(gwNode -> setRulesForSnatIngressRule(
1327 gwNode.intgBridge(),
Jian Li4d138702018-11-27 17:25:28 +09001328 Long.parseLong(network.getProviderSegID()),
1329 IpPrefix.valueOf(instPort.ipAddress(), VM_PREFIX),
SONA Project6bc5c4a2018-12-14 23:49:52 +09001330 instPort.deviceId(), netType, false));
Daniel Parkc64b4c62018-05-09 18:13:39 +09001331 }
sangho072c4dd2017-05-17 10:45:21 +09001332 }
1333 }
Hyunsun Moon44aac662017-02-18 02:07:01 +09001334}