blob: 0a915b79e0707e13fbf87f6cd0fe0ff857fccfcb [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;
20import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
sanghoe765ce22017-06-23 17:54:57 +090023import org.apache.felix.scr.annotations.Modified;
24import org.apache.felix.scr.annotations.Property;
Hyunsun Moon44aac662017-02-18 02:07:01 +090025import org.apache.felix.scr.annotations.Reference;
26import org.apache.felix.scr.annotations.ReferenceCardinality;
27import org.onlab.packet.Ethernet;
sanghoe765ce22017-06-23 17:54:57 +090028import org.onlab.packet.ICMP;
Hyunsun Moon44aac662017-02-18 02:07:01 +090029import org.onlab.packet.IPv4;
30import org.onlab.packet.IpAddress;
31import org.onlab.packet.IpPrefix;
sangho072c4dd2017-05-17 10:45:21 +090032import org.onlab.packet.MacAddress;
daniel parkee8700b2017-05-11 15:50:03 +090033import org.onlab.packet.VlanId;
sanghoe765ce22017-06-23 17:54:57 +090034import org.onlab.util.Tools;
35import org.onosproject.cfg.ComponentConfigService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090036import org.onosproject.cluster.ClusterService;
37import org.onosproject.cluster.LeadershipService;
38import org.onosproject.cluster.NodeId;
39import org.onosproject.core.ApplicationId;
40import org.onosproject.core.CoreService;
sangho072c4dd2017-05-17 10:45:21 +090041import org.onosproject.mastership.MastershipService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090042import org.onosproject.net.DeviceId;
43import org.onosproject.net.PortNumber;
sangho072c4dd2017-05-17 10:45:21 +090044import org.onosproject.net.device.DeviceService;
45import org.onosproject.net.driver.DriverService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090046import org.onosproject.net.flow.DefaultTrafficSelector;
47import org.onosproject.net.flow.DefaultTrafficTreatment;
48import org.onosproject.net.flow.TrafficSelector;
49import org.onosproject.net.flow.TrafficTreatment;
sangho072c4dd2017-05-17 10:45:21 +090050import org.onosproject.net.flow.instructions.ExtensionTreatment;
Hyunsun Moon44aac662017-02-18 02:07:01 +090051import org.onosproject.openstacknetworking.api.Constants;
sangho072c4dd2017-05-17 10:45:21 +090052import org.onosproject.openstacknetworking.api.InstancePort;
53import org.onosproject.openstacknetworking.api.InstancePortEvent;
54import org.onosproject.openstacknetworking.api.InstancePortListener;
55import org.onosproject.openstacknetworking.api.InstancePortService;
sanghodc375372017-06-08 10:41:30 +090056import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090057import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
58import org.onosproject.openstacknetworking.api.OpenstackRouterEvent;
59import org.onosproject.openstacknetworking.api.OpenstackRouterListener;
60import org.onosproject.openstacknetworking.api.OpenstackRouterService;
Hyunsun Moon0d457362017-06-27 17:19:41 +090061import org.onosproject.openstacknode.api.OpenstackNode;
62import org.onosproject.openstacknode.api.OpenstackNode.NetworkMode;
63import org.onosproject.openstacknode.api.OpenstackNodeEvent;
64import org.onosproject.openstacknode.api.OpenstackNodeListener;
65import org.onosproject.openstacknode.api.OpenstackNodeService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090066import org.openstack4j.model.network.ExternalGateway;
67import org.openstack4j.model.network.Network;
daniel parkee8700b2017-05-11 15:50:03 +090068import org.openstack4j.model.network.NetworkType;
Hyunsun Moon44aac662017-02-18 02:07:01 +090069import org.openstack4j.model.network.Router;
70import org.openstack4j.model.network.RouterInterface;
71import org.openstack4j.model.network.Subnet;
sanghoe765ce22017-06-23 17:54:57 +090072import org.osgi.service.component.ComponentContext;
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;
87import static org.onosproject.openstacknetworking.api.Constants.FORWARDING_TABLE;
88import static org.onosproject.openstacknetworking.api.Constants.GW_COMMON_TABLE;
89import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
90import 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;
Frank Wang245a6822017-06-14 09:51:35 +080096import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ADMIN_RULE;
sangho072c4dd2017-05-17 10:45:21 +090097import static org.onosproject.openstacknetworking.impl.RulePopulatorUtil.buildExtension;
Hyunsun Moon0d457362017-06-27 17:19:41 +090098import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
99import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900100
101/**
102 * Handles OpenStack router events.
103 */
104@Component(immediate = true)
105public class OpenstackRoutingHandler {
106
107 private final Logger log = LoggerFactory.getLogger(getClass());
108
109 private static final String MSG_ENABLED = "Enabled ";
110 private static final String MSG_DISABLED = "Disabled ";
111 private static final String ERR_SET_FLOWS = "Failed to set flows for router %s:";
daniel parkee8700b2017-05-11 15:50:03 +0900112 private static final String ERR_UNSUPPORTED_NET_TYPE = "Unsupported network type";
sanghoe765ce22017-06-23 17:54:57 +0900113 private static final boolean USE_STATEFUL_SNAT = false;
114
115 @Property(name = "useStatefulSnat", boolValue = USE_STATEFUL_SNAT,
116 label = "Use Stateful SNAT for source NATing")
117 private boolean useStatefulSnat = USE_STATEFUL_SNAT;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900118
119 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
120 protected CoreService coreService;
121
122 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
123 protected LeadershipService leadershipService;
124
125 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
126 protected ClusterService clusterService;
127
128 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900129 protected OpenstackNodeService osNodeService;
130
131 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900132 protected OpenstackNetworkService osNetworkService;
133
134 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
135 protected OpenstackRouterService osRouterService;
136
daniel parkee8700b2017-05-11 15:50:03 +0900137 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sangho072c4dd2017-05-17 10:45:21 +0900138 protected InstancePortService instancePortService;
139
140 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
141 protected DeviceService deviceService;
142
143 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sanghodc375372017-06-08 10:41:30 +0900144 protected OpenstackFlowRuleService osFlowRuleService;
145
sangho072c4dd2017-05-17 10:45:21 +0900146 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
147 protected MastershipService mastershipService;
148
149 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
150 protected DriverService driverService;
151
sanghoe765ce22017-06-23 17:54:57 +0900152 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
153 protected ComponentConfigService configService;
154
Hyunsun Moon44aac662017-02-18 02:07:01 +0900155 private final ExecutorService eventExecutor = newSingleThreadScheduledExecutor(
156 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
157 private final OpenstackNodeListener osNodeListener = new InternalNodeEventListener();
158 private final OpenstackRouterListener osRouterListener = new InternalRouterEventListener();
sangho072c4dd2017-05-17 10:45:21 +0900159 private final InstancePortListener instancePortListener = new InternalInstancePortListener();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900160
161 private ApplicationId appId;
162 private NodeId localNodeId;
163
164 @Activate
165 protected void activate() {
166 appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
167 localNodeId = clusterService.getLocalNode().id();
168 leadershipService.runForLeadership(appId.name());
169 osNodeService.addListener(osNodeListener);
170 osRouterService.addListener(osRouterListener);
sangho072c4dd2017-05-17 10:45:21 +0900171 instancePortService.addListener(instancePortListener);
sanghoe765ce22017-06-23 17:54:57 +0900172 configService.registerProperties(getClass());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900173
174 log.info("Started");
175 }
176
177 @Deactivate
178 protected void deactivate() {
179 osRouterService.removeListener(osRouterListener);
180 osNodeService.removeListener(osNodeListener);
sangho072c4dd2017-05-17 10:45:21 +0900181 instancePortService.removeListener(instancePortListener);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900182 leadershipService.withdraw(appId.name());
sanghoe765ce22017-06-23 17:54:57 +0900183 configService.unregisterProperties(getClass(), false);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900184 eventExecutor.shutdown();
185
186 log.info("Stopped");
187 }
188
sanghoe765ce22017-06-23 17:54:57 +0900189 @Modified
190 protected void modified(ComponentContext context) {
191 Dictionary<?, ?> properties = context.getProperties();
192 Boolean flag;
193
194 flag = Tools.isPropertyEnabled(properties, "useStatefulSnat");
195 if (flag == null) {
196 log.info("useStatefulSnat is not configured, " +
197 "using current value of {}", useStatefulSnat);
198 } else {
199 useStatefulSnat = flag;
200 log.info("Configured. useStatefulSnat is {}",
201 useStatefulSnat ? "enabled" : "disabled");
202 }
203
204 resetSnatRules();
205 }
206
Hyunsun Moon44aac662017-02-18 02:07:01 +0900207 private void routerUpdated(Router osRouter) {
208 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
Frank Wang245a6822017-06-14 09:51:35 +0800209 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
210 Network network = osNetworkService.network(osNetworkService.subnet(iface.getSubnetId())
211 .getNetworkId());
212 setRouterAdminRules(network.getProviderSegID(), network.getNetworkType(), !osRouter.isAdminStateUp());
213 });
214
Hyunsun Moon44aac662017-02-18 02:07:01 +0900215 if (exGateway == null) {
daniel parkb5817102018-02-15 00:18:51 +0900216 osNetworkService.deleteExternalPeerRouter(exGateway);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900217 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
sangho072c4dd2017-05-17 10:45:21 +0900218 setSourceNat(osRouter, iface, false);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900219 });
220 } else {
daniel parkb5817102018-02-15 00:18:51 +0900221 osNetworkService.deriveExternalPeerRouterMac(exGateway, osRouter);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900222 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
sangho072c4dd2017-05-17 10:45:21 +0900223 setSourceNat(osRouter, iface, exGateway.isEnableSnat());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900224 });
225 }
226 }
227
Frank Wang245a6822017-06-14 09:51:35 +0800228 private void routerRemove(Router osRouter) {
229 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
230 Network network = osNetworkService.network(osNetworkService.subnet(iface.getSubnetId())
231 .getNetworkId());
232 setRouterAdminRules(network.getProviderSegID(), network.getNetworkType(), false);
233 });
234 }
235
Hyunsun Moon44aac662017-02-18 02:07:01 +0900236 private void routerIfaceAdded(Router osRouter, RouterInterface osRouterIface) {
237 Subnet osSubnet = osNetworkService.subnet(osRouterIface.getSubnetId());
238 if (osSubnet == null) {
239 final String error = String.format(
240 ERR_SET_FLOWS + "subnet %s does not exist",
241 osRouterIface.getId(),
242 osRouterIface.getSubnetId());
243 throw new IllegalStateException(error);
244 }
Frank Wang245a6822017-06-14 09:51:35 +0800245
246 if (!osRouter.isAdminStateUp()) {
247 Network network = osNetworkService.network(osSubnet.getNetworkId());
248 setRouterAdminRules(network.getProviderSegID(), network.getNetworkType(), true);
249 }
250
Hyunsun Moon44aac662017-02-18 02:07:01 +0900251 setInternalRoutes(osRouter, osSubnet, true);
252 setGatewayIcmp(osSubnet, true);
253 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
254 if (exGateway != null && exGateway.isEnableSnat()) {
sangho072c4dd2017-05-17 10:45:21 +0900255 setSourceNat(osRouter, osRouterIface, true);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900256 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900257 log.info("Connected subnet({}) to {}", osSubnet.getCidr(), osRouter.getName());
258 }
259
260 private void routerIfaceRemoved(Router osRouter, RouterInterface osRouterIface) {
261 Subnet osSubnet = osNetworkService.subnet(osRouterIface.getSubnetId());
262 if (osSubnet == null) {
263 final String error = String.format(
264 ERR_SET_FLOWS + "subnet %s does not exist",
265 osRouterIface.getId(),
266 osRouterIface.getSubnetId());
267 throw new IllegalStateException(error);
268 }
269
Frank Wang245a6822017-06-14 09:51:35 +0800270 if (!osRouter.isAdminStateUp()) {
271 Network network = osNetworkService.network(osSubnet.getNetworkId());
272 setRouterAdminRules(network.getProviderSegID(), network.getNetworkType(), false);
273 }
274
Hyunsun Moon44aac662017-02-18 02:07:01 +0900275 setInternalRoutes(osRouter, osSubnet, false);
276 setGatewayIcmp(osSubnet, false);
277 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
278 if (exGateway != null && exGateway.isEnableSnat()) {
sangho072c4dd2017-05-17 10:45:21 +0900279 setSourceNat(osRouter, osRouterIface, false);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900280 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900281 log.info("Disconnected subnet({}) from {}", osSubnet.getCidr(), osRouter.getName());
282 }
283
sangho072c4dd2017-05-17 10:45:21 +0900284 private void setSourceNat(Router osRouter, RouterInterface routerIface, boolean install) {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900285 Subnet osSubnet = osNetworkService.subnet(routerIface.getSubnetId());
286 Network osNet = osNetworkService.network(osSubnet.getNetworkId());
287
Hyunsun Moon0d457362017-06-27 17:19:41 +0900288 osNodeService.completeNodes(COMPUTE).forEach(cNode -> {
289 setRulesToGateway(cNode, osNet.getProviderSegID(),
290 IpPrefix.valueOf(osSubnet.getCidr()), osNet.getNetworkType(),
291 install);
292 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900293
sanghoe765ce22017-06-23 17:54:57 +0900294 if (useStatefulSnat) {
295 setStatefulSnatRules(routerIface, install);
296 } else {
297 setReactiveSnatRules(routerIface, install);
298 }
299
300 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
301 log.info(updateStr + "external access for subnet({})", osSubnet.getCidr());
302 }
303
304 private void setStatefulSnatRules(RouterInterface routerIface, boolean install) {
305 Subnet osSubnet = osNetworkService.subnet(routerIface.getSubnetId());
306 Network osNet = osNetworkService.network(osSubnet.getNetworkId());
307
308 Optional<Router> osRouter = osRouterService.routers().stream()
309 .filter(router -> osRouterService.routerInterfaces(routerIface.getId()) != null)
310 .findAny();
311
312 if (!osRouter.isPresent()) {
313 log.error("Cannot find a router for router interface {} ", routerIface);
314 return;
315 }
316 IpAddress natAddress = getGatewayIpAddress(osRouter.get());
sangho072c4dd2017-05-17 10:45:21 +0900317 if (natAddress == null) {
318 return;
319 }
320 String netId = osNetworkService.subnet(routerIface.getSubnetId()).getNetworkId();
321
322 osNodeService.completeNodes(OpenstackNode.NodeType.GATEWAY)
323 .forEach(gwNode -> {
324 instancePortService.instancePorts(netId).stream()
325 .forEach(port -> setRulesForSnatIngressRule(gwNode.intgBridge(),
326 Long.parseLong(osNet.getProviderSegID()),
327 IpPrefix.valueOf(port.ipAddress(), 32),
328 port.deviceId(),
329 install));
330
331 setOvsNatIngressRule(gwNode.intgBridge(),
332 IpPrefix.valueOf(natAddress, 32),
333 Constants.DEFAULT_EXTERNAL_ROUTER_MAC, install);
334 setOvsNatEgressRule(gwNode.intgBridge(),
335 natAddress, Long.parseLong(osNet.getProviderSegID()),
336 gwNode.patchPortNum(), install);
337 });
sanghoe765ce22017-06-23 17:54:57 +0900338 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900339
sanghoe765ce22017-06-23 17:54:57 +0900340 private void setReactiveSnatRules(RouterInterface routerIface, boolean install) {
341 Subnet osSubnet = osNetworkService.subnet(routerIface.getSubnetId());
342 Network osNet = osNetworkService.network(osSubnet.getNetworkId());
343
344 osNodeService.completeNodes(GATEWAY)
345 .forEach(gwNode -> setRulesToController(
346 gwNode.intgBridge(),
347 osNet.getProviderSegID(),
348 IpPrefix.valueOf(osSubnet.getCidr()),
349 osNet.getNetworkType(),
350 install));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900351 }
352
sangho072c4dd2017-05-17 10:45:21 +0900353 private IpAddress getGatewayIpAddress(Router osRouter) {
354
355 String extNetId = osNetworkService.network(osRouter.getExternalGatewayInfo().getNetworkId()).getId();
356 Optional<Subnet> extSubnet = osNetworkService.subnets().stream()
357 .filter(subnet -> subnet.getNetworkId().equals(extNetId))
358 .findAny();
359
360 if (!extSubnet.isPresent()) {
361 log.error("Cannot find externel subnet for the router");
362 return null;
363 }
364
365 return IpAddress.valueOf(extSubnet.get().getGateway());
366 }
367
sanghoe765ce22017-06-23 17:54:57 +0900368 private void resetSnatRules() {
369 if (useStatefulSnat) {
370 osRouterService.routerInterfaces().forEach(
371 routerIface -> {
372 setReactiveSnatRules(routerIface, false);
373 setStatefulSnatRules(routerIface, true);
374 }
375 );
376 } else {
377 osRouterService.routerInterfaces().forEach(
378 routerIface -> {
379 setStatefulSnatRules(routerIface, false);
380 setReactiveSnatRules(routerIface, true);
381 }
382 );
383 }
384 }
385
Hyunsun Moon44aac662017-02-18 02:07:01 +0900386 private void setGatewayIcmp(Subnet osSubnet, boolean install) {
daniel parkb5817102018-02-15 00:18:51 +0900387 OpenstackNode sourceNatGateway = osNodeService.completeNodes(GATEWAY).stream().findFirst().orElse(null);
388
389 if (sourceNatGateway == null) {
390 return;
391 }
392
Hyunsun Moon44aac662017-02-18 02:07:01 +0900393 if (Strings.isNullOrEmpty(osSubnet.getGateway())) {
394 // do nothing if no gateway is set
395 return;
396 }
397
398 // take ICMP request to a subnet gateway through gateway node group
399 Network network = osNetworkService.network(osSubnet.getNetworkId());
daniel parkee8700b2017-05-11 15:50:03 +0900400 switch (network.getNetworkType()) {
401 case VXLAN:
Hyunsun Moon0d457362017-06-27 17:19:41 +0900402 osNodeService.completeNodes(COMPUTE).stream()
403 .filter(cNode -> cNode.dataIp() != null)
404 .forEach(cNode -> setRulesToGatewayWithDstIp(
405 cNode,
daniel parkb5817102018-02-15 00:18:51 +0900406 sourceNatGateway,
daniel parkee8700b2017-05-11 15:50:03 +0900407 network.getProviderSegID(),
408 IpAddress.valueOf(osSubnet.getGateway()),
409 NetworkMode.VXLAN,
410 install));
411 break;
412 case VLAN:
Hyunsun Moon0d457362017-06-27 17:19:41 +0900413 osNodeService.completeNodes(COMPUTE).stream()
414 .filter(cNode -> cNode.vlanPortNum() != null)
415 .forEach(cNode -> setRulesToGatewayWithDstIp(
416 cNode,
daniel parkb5817102018-02-15 00:18:51 +0900417 sourceNatGateway,
daniel parkee8700b2017-05-11 15:50:03 +0900418 network.getProviderSegID(),
419 IpAddress.valueOf(osSubnet.getGateway()),
420 NetworkMode.VLAN,
421 install));
422 break;
423 default:
424 final String error = String.format(
425 ERR_UNSUPPORTED_NET_TYPE + "%s",
426 network.getNetworkType().toString());
427 throw new IllegalStateException(error);
428 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900429
430 IpAddress gatewayIp = IpAddress.valueOf(osSubnet.getGateway());
Hyunsun Moon0d457362017-06-27 17:19:41 +0900431 osNodeService.completeNodes(GATEWAY).forEach(gNode -> {
432 setGatewayIcmpRule(
433 gatewayIp,
434 gNode.intgBridge(),
435 install
436 );
437 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900438
439 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
440 log.debug(updateStr + "ICMP to {}", osSubnet.getGateway());
441 }
442
443 private void setInternalRoutes(Router osRouter, Subnet updatedSubnet, boolean install) {
daniel parkee8700b2017-05-11 15:50:03 +0900444 Network updatedNetwork = osNetworkService.network(updatedSubnet.getNetworkId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900445 Set<Subnet> routableSubnets = routableSubnets(osRouter, updatedSubnet.getId());
daniel parkee8700b2017-05-11 15:50:03 +0900446 String updatedSegmendId = getSegmentId(updatedSubnet);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900447
448 // installs rule from/to my subnet intentionally to fix ICMP failure
449 // to my subnet gateway if no external gateway added to the router
Hyunsun Moon0d457362017-06-27 17:19:41 +0900450 osNodeService.completeNodes(COMPUTE).forEach(cNode -> {
451 setInternalRouterRules(
452 cNode.intgBridge(),
453 updatedSegmendId,
454 updatedSegmendId,
455 IpPrefix.valueOf(updatedSubnet.getCidr()),
456 IpPrefix.valueOf(updatedSubnet.getCidr()),
457 updatedNetwork.getNetworkType(),
458 install
459 );
Hyunsun Moon44aac662017-02-18 02:07:01 +0900460
Hyunsun Moon0d457362017-06-27 17:19:41 +0900461 routableSubnets.forEach(subnet -> {
462 setInternalRouterRules(
463 cNode.intgBridge(),
464 updatedSegmendId,
465 getSegmentId(subnet),
466 IpPrefix.valueOf(updatedSubnet.getCidr()),
467 IpPrefix.valueOf(subnet.getCidr()),
468 updatedNetwork.getNetworkType(),
469 install
470 );
471 setInternalRouterRules(
472 cNode.intgBridge(),
473 getSegmentId(subnet),
474 updatedSegmendId,
475 IpPrefix.valueOf(subnet.getCidr()),
476 IpPrefix.valueOf(updatedSubnet.getCidr()),
477 updatedNetwork.getNetworkType(),
478 install
479 );
480 });
481 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900482
daniel parkee8700b2017-05-11 15:50:03 +0900483
Hyunsun Moon44aac662017-02-18 02:07:01 +0900484 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
485 routableSubnets.forEach(subnet -> log.debug(
486 updateStr + "route between subnet:{} and subnet:{}",
487 subnet.getCidr(),
488 updatedSubnet.getCidr()));
489 }
490
491 private Set<Subnet> routableSubnets(Router osRouter, String osSubnetId) {
492 Set<Subnet> osSubnets = osRouterService.routerInterfaces(osRouter.getId())
493 .stream()
494 .filter(iface -> !Objects.equals(iface.getSubnetId(), osSubnetId))
495 .map(iface -> osNetworkService.subnet(iface.getSubnetId()))
496 .collect(Collectors.toSet());
497 return ImmutableSet.copyOf(osSubnets);
498 }
499
daniel parkee8700b2017-05-11 15:50:03 +0900500 private String getSegmentId(Subnet osSubnet) {
501 return osNetworkService.network(osSubnet.getNetworkId()).getProviderSegID();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900502 }
503
504 private void setGatewayIcmpRule(IpAddress gatewayIp, DeviceId deviceId, boolean install) {
505 TrafficSelector selector = DefaultTrafficSelector.builder()
506 .matchEthType(Ethernet.TYPE_IPV4)
507 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900508 .matchIPDst(gatewayIp.getIp4Address().toIpPrefix())
Hyunsun Moon44aac662017-02-18 02:07:01 +0900509 .build();
510
511 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
512 .setOutput(PortNumber.CONTROLLER)
513 .build();
514
sanghodc375372017-06-08 10:41:30 +0900515 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900516 appId,
517 deviceId,
518 selector,
519 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900520 PRIORITY_ICMP_RULE,
sanghodc375372017-06-08 10:41:30 +0900521 Constants.GW_COMMON_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900522 install);
523 }
524
daniel parkee8700b2017-05-11 15:50:03 +0900525 private void setInternalRouterRules(DeviceId deviceId, String srcSegmentId, String dstSegmentId,
526 IpPrefix srcSubnet, IpPrefix dstSubnet,
527 NetworkType networkType, boolean install) {
528 TrafficSelector selector;
529 TrafficTreatment treatment;
530 switch (networkType) {
531 case VXLAN:
532 selector = DefaultTrafficSelector.builder()
533 .matchEthType(Ethernet.TYPE_IPV4)
534 .matchTunnelId(Long.parseLong(srcSegmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900535 .matchIPSrc(srcSubnet.getIp4Prefix())
536 .matchIPDst(dstSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900537 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900538
daniel parkee8700b2017-05-11 15:50:03 +0900539 treatment = DefaultTrafficTreatment.builder()
540 .setTunnelId(Long.parseLong(dstSegmentId))
sanghodc375372017-06-08 10:41:30 +0900541 .transition(FORWARDING_TABLE)
daniel parkee8700b2017-05-11 15:50:03 +0900542 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900543
sanghodc375372017-06-08 10:41:30 +0900544 osFlowRuleService.setRule(
daniel parkee8700b2017-05-11 15:50:03 +0900545 appId,
546 deviceId,
547 selector,
548 treatment,
daniel parkee8700b2017-05-11 15:50:03 +0900549 PRIORITY_INTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900550 ROUTING_TABLE,
daniel parkee8700b2017-05-11 15:50:03 +0900551 install);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900552
daniel parkee8700b2017-05-11 15:50:03 +0900553 selector = DefaultTrafficSelector.builder()
554 .matchEthType(Ethernet.TYPE_IPV4)
555 .matchTunnelId(Long.parseLong(dstSegmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900556 .matchIPSrc(srcSubnet.getIp4Prefix())
557 .matchIPDst(dstSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900558 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900559
daniel parkee8700b2017-05-11 15:50:03 +0900560 treatment = DefaultTrafficTreatment.builder()
561 .setTunnelId(Long.parseLong(dstSegmentId))
sanghodc375372017-06-08 10:41:30 +0900562 .transition(FORWARDING_TABLE)
daniel parkee8700b2017-05-11 15:50:03 +0900563 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900564
sanghodc375372017-06-08 10:41:30 +0900565 osFlowRuleService.setRule(
daniel parkee8700b2017-05-11 15:50:03 +0900566 appId,
567 deviceId,
568 selector,
569 treatment,
daniel parkee8700b2017-05-11 15:50:03 +0900570 PRIORITY_INTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900571 ROUTING_TABLE,
daniel parkee8700b2017-05-11 15:50:03 +0900572 install);
573 break;
574 case VLAN:
575 selector = DefaultTrafficSelector.builder()
576 .matchEthType(Ethernet.TYPE_IPV4)
577 .matchVlanId(VlanId.vlanId(srcSegmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900578 .matchIPSrc(srcSubnet.getIp4Prefix())
579 .matchIPDst(dstSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900580 .build();
581
582 treatment = DefaultTrafficTreatment.builder()
583 .setVlanId(VlanId.vlanId(dstSegmentId))
sanghodc375372017-06-08 10:41:30 +0900584 .transition(FORWARDING_TABLE)
daniel parkee8700b2017-05-11 15:50:03 +0900585 .build();
586
sanghodc375372017-06-08 10:41:30 +0900587 osFlowRuleService.setRule(
daniel parkee8700b2017-05-11 15:50:03 +0900588 appId,
589 deviceId,
590 selector,
591 treatment,
daniel parkee8700b2017-05-11 15:50:03 +0900592 PRIORITY_INTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900593 ROUTING_TABLE,
daniel parkee8700b2017-05-11 15:50:03 +0900594 install);
595
596 selector = DefaultTrafficSelector.builder()
597 .matchEthType(Ethernet.TYPE_IPV4)
598 .matchVlanId(VlanId.vlanId(dstSegmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900599 .matchIPSrc(srcSubnet.getIp4Prefix())
600 .matchIPDst(dstSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900601 .build();
602
603 treatment = DefaultTrafficTreatment.builder()
604 .setVlanId(VlanId.vlanId(dstSegmentId))
sanghodc375372017-06-08 10:41:30 +0900605 .transition(FORWARDING_TABLE)
daniel parkee8700b2017-05-11 15:50:03 +0900606 .build();
607
sanghodc375372017-06-08 10:41:30 +0900608 osFlowRuleService.setRule(
daniel parkee8700b2017-05-11 15:50:03 +0900609 appId,
610 deviceId,
611 selector,
612 treatment,
daniel parkee8700b2017-05-11 15:50:03 +0900613 PRIORITY_INTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900614 ROUTING_TABLE,
daniel parkee8700b2017-05-11 15:50:03 +0900615 install);
616 break;
617 default:
618 final String error = String.format(
619 ERR_UNSUPPORTED_NET_TYPE + "%s",
620 networkType.toString());
621 throw new IllegalStateException(error);
622 }
623
Hyunsun Moon44aac662017-02-18 02:07:01 +0900624 }
625
Hyunsun Moon0d457362017-06-27 17:19:41 +0900626 private void setRulesToGateway(OpenstackNode osNode, String segmentId, IpPrefix srcSubnet,
daniel parkee8700b2017-05-11 15:50:03 +0900627 NetworkType networkType, boolean install) {
628 TrafficTreatment treatment;
daniel parkb5817102018-02-15 00:18:51 +0900629 OpenstackNode sourceNatGateway = osNodeService.completeNodes(GATEWAY).stream().findFirst().orElse(null);
630
631 if (sourceNatGateway == null) {
632 return;
633 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900634
daniel parkee8700b2017-05-11 15:50:03 +0900635 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
636 .matchEthType(Ethernet.TYPE_IPV4)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900637 .matchIPSrc(srcSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900638 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
639
640 switch (networkType) {
641 case VXLAN:
642 sBuilder.matchTunnelId(Long.parseLong(segmentId));
daniel parkee8700b2017-05-11 15:50:03 +0900643 break;
644 case VLAN:
645 sBuilder.matchVlanId(VlanId.vlanId(segmentId));
daniel parkee8700b2017-05-11 15:50:03 +0900646 break;
647 default:
648 final String error = String.format(
649 ERR_UNSUPPORTED_NET_TYPE + "%s",
650 networkType.toString());
651 throw new IllegalStateException(error);
652 }
653
654 treatment = DefaultTrafficTreatment.builder()
daniel parkb5817102018-02-15 00:18:51 +0900655 .extension(buildExtension(
656 deviceService,
657 osNode.intgBridge(),
658 sourceNatGateway.dataIp().getIp4Address()),
659 osNode.intgBridge())
660 .setOutput(osNode.tunnelPortNum())
Hyunsun Moon44aac662017-02-18 02:07:01 +0900661 .build();
662
sanghodc375372017-06-08 10:41:30 +0900663 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900664 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900665 osNode.intgBridge(),
daniel parkee8700b2017-05-11 15:50:03 +0900666 sBuilder.build(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900667 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900668 PRIORITY_EXTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900669 ROUTING_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900670 install);
671 }
672
sangho072c4dd2017-05-17 10:45:21 +0900673 private void setRulesForSnatIngressRule(DeviceId deviceId, Long vni, IpPrefix destVmIp,
674 DeviceId dstDeviceId, boolean install) {
675
676 TrafficSelector selector = DefaultTrafficSelector.builder()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900677 .matchEthType(Ethernet.TYPE_IPV4)
sangho072c4dd2017-05-17 10:45:21 +0900678 .matchIPDst(destVmIp)
679 .build();
Hyunsun Moon0d457362017-06-27 17:19:41 +0900680
sangho072c4dd2017-05-17 10:45:21 +0900681 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
682 .setTunnelId(vni)
683 .extension(buildExtension(
684 deviceService,
685 deviceId,
686 osNodeService.node(dstDeviceId).dataIp().getIp4Address()),
687 deviceId)
688 .setOutput(osNodeService.node(deviceId).tunnelPortNum())
689 .build();
daniel parkee8700b2017-05-11 15:50:03 +0900690
sanghodc375372017-06-08 10:41:30 +0900691 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900692 appId,
sangho072c4dd2017-05-17 10:45:21 +0900693 deviceId,
694 selector,
695 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900696 PRIORITY_EXTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900697 Constants.GW_COMMON_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900698 install);
699 }
700
daniel parkb5817102018-02-15 00:18:51 +0900701 private void setRulesToGatewayWithDstIp(OpenstackNode osNode, OpenstackNode sourceNatGateway,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900702 String segmentId, IpAddress dstIp,
703 NetworkMode networkMode, boolean install) {
daniel parkee8700b2017-05-11 15:50:03 +0900704 TrafficSelector selector;
705 if (networkMode.equals(NetworkMode.VXLAN)) {
706 selector = DefaultTrafficSelector.builder()
707 .matchEthType(Ethernet.TYPE_IPV4)
708 .matchTunnelId(Long.valueOf(segmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900709 .matchIPDst(dstIp.getIp4Address().toIpPrefix())
daniel parkee8700b2017-05-11 15:50:03 +0900710 .build();
711 } else {
712 selector = DefaultTrafficSelector.builder()
713 .matchEthType(Ethernet.TYPE_IPV4)
714 .matchVlanId(VlanId.vlanId(segmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900715 .matchIPDst(dstIp.getIp4Address().toIpPrefix())
daniel parkee8700b2017-05-11 15:50:03 +0900716 .build();
717 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900718
719 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
daniel parkb5817102018-02-15 00:18:51 +0900720 .extension(buildExtension(
721 deviceService,
722 osNode.intgBridge(),
723 sourceNatGateway.dataIp().getIp4Address()),
724 osNode.intgBridge())
725 .setOutput(osNode.tunnelPortNum())
Hyunsun Moon44aac662017-02-18 02:07:01 +0900726 .build();
727
sanghodc375372017-06-08 10:41:30 +0900728 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900729 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900730 osNode.intgBridge(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900731 selector,
732 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900733 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900734 ROUTING_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900735 install);
736 }
737
sangho072c4dd2017-05-17 10:45:21 +0900738 private void setOvsNatIngressRule(DeviceId deviceId, IpPrefix cidr, MacAddress dstMac, boolean install) {
739
740 TrafficSelector selector = DefaultTrafficSelector.builder()
741 .matchEthType(Ethernet.TYPE_IPV4)
742 .matchIPDst(cidr)
743 .build();
744
745 ExtensionTreatment natTreatment = RulePopulatorUtil.niciraConnTrackTreatmentBuilder(driverService, deviceId)
746 .commit(false)
747 .natAction(true)
748 .table((short) 0)
749 .build();
750
751 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
752 .setEthDst(dstMac)
753 .extension(natTreatment, deviceId)
754 .build();
755
756 osFlowRuleService.setRule(
757 appId,
758 deviceId,
759 selector,
760 treatment,
sanghoe765ce22017-06-23 17:54:57 +0900761 PRIORITY_STATEFUL_SNAT_RULE,
sangho072c4dd2017-05-17 10:45:21 +0900762 GW_COMMON_TABLE,
763 install);
764 }
765
766 private void setOvsNatEgressRule(DeviceId deviceId, IpAddress natAddress, long vni, PortNumber output,
767 boolean install) {
768
769 TrafficSelector selector = DefaultTrafficSelector.builder()
770 .matchEthType(Ethernet.TYPE_IPV4)
771 .matchEthDst(DEFAULT_GATEWAY_MAC)
772 .matchTunnelId(vni)
773 .build();
774
775 ExtensionTreatment natTreatment = RulePopulatorUtil.niciraConnTrackTreatmentBuilder(driverService, deviceId)
776 .commit(true)
777 .natAction(true)
778 .natIp(natAddress)
779 .build();
780
781 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
782 .extension(natTreatment, deviceId)
783 .setEthDst(DEFAULT_EXTERNAL_ROUTER_MAC)
784 .setEthSrc(DEFAULT_GATEWAY_MAC)
785 .setOutput(output)
786 .build();
787
788 osFlowRuleService.setRule(
789 appId,
790 deviceId,
791 selector,
792 treatment,
sanghoe765ce22017-06-23 17:54:57 +0900793 PRIORITY_STATEFUL_SNAT_RULE,
sangho072c4dd2017-05-17 10:45:21 +0900794 GW_COMMON_TABLE,
795 install);
796 }
797
sanghoe765ce22017-06-23 17:54:57 +0900798 private void setRulesToController(DeviceId deviceId, String segmentId, IpPrefix srcSubnet,
799 NetworkType networkType, boolean install) {
800 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
801 .matchEthType(Ethernet.TYPE_IPV4)
802 .matchIPSrc(srcSubnet);
803
804 switch (networkType) {
805 case VXLAN:
806 sBuilder.matchTunnelId(Long.parseLong(segmentId))
807 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
808 break;
809 case VLAN:
810 sBuilder.matchVlanId(VlanId.vlanId(segmentId))
811 .matchEthDst(osNodeService.node(deviceId).vlanPortMac());
812 break;
813 default:
814 final String error = String.format(
815 ERR_UNSUPPORTED_NET_TYPE + "%s",
816 networkType.toString());
817 throw new IllegalStateException(error);
818 }
819
820 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
821 .setEthDst(Constants.DEFAULT_GATEWAY_MAC);
822
823 if (networkType.equals(NetworkType.VLAN)) {
824 tBuilder.popVlan();
825 }
826
827 tBuilder.setOutput(PortNumber.CONTROLLER);
828
829 osFlowRuleService.setRule(
830 appId,
831 deviceId,
832 sBuilder.build(),
833 tBuilder.build(),
834 PRIORITY_EXTERNAL_ROUTING_RULE,
835 GW_COMMON_TABLE,
836 install);
837
838
839 // Sends ICMP response to controller for SNATing ingress traffic
840 TrafficSelector selector = DefaultTrafficSelector.builder()
841 .matchEthType(Ethernet.TYPE_IPV4)
842 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
843 .matchIcmpType(ICMP.TYPE_ECHO_REPLY)
844 .build();
845
846 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
847 .setOutput(PortNumber.CONTROLLER)
848 .build();
849
850 osFlowRuleService.setRule(
851 appId,
852 deviceId,
853 selector,
854 treatment,
855 PRIORITY_INTERNAL_ROUTING_RULE,
856 GW_COMMON_TABLE,
857 install);
858 }
sangho072c4dd2017-05-17 10:45:21 +0900859
Frank Wang245a6822017-06-14 09:51:35 +0800860 private void setRouterAdminRules(String segmentId, NetworkType networkType, boolean install) {
861 TrafficTreatment treatment;
862 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
863 .matchEthType(Ethernet.TYPE_IPV4);
864
865 switch (networkType) {
866 case VXLAN:
867 sBuilder.matchTunnelId(Long.parseLong(segmentId));
868 break;
869 case VLAN:
870 sBuilder.matchVlanId(VlanId.vlanId(segmentId));
871 break;
872 default:
873 final String error = String.format(
874 ERR_UNSUPPORTED_NET_TYPE + "%s",
875 networkType.toString());
876 throw new IllegalStateException(error);
877 }
878
879 treatment = DefaultTrafficTreatment.builder()
880 .drop()
881 .build();
882
883 osNodeService.completeNodes().stream()
884 .filter(osNode -> osNode.type() == COMPUTE)
885 .forEach(osNode -> {
886 osFlowRuleService.setRule(
887 appId,
888 osNode.intgBridge(),
889 sBuilder.build(),
890 treatment,
891 PRIORITY_ADMIN_RULE,
892 ROUTING_TABLE,
893 install);
894 });
895 }
896
Hyunsun Moon44aac662017-02-18 02:07:01 +0900897 private class InternalRouterEventListener implements OpenstackRouterListener {
898
899 @Override
900 public boolean isRelevant(OpenstackRouterEvent event) {
901 // do not allow to proceed without leadership
902 NodeId leader = leadershipService.getLeader(appId.name());
903 return Objects.equals(localNodeId, leader);
904 }
905
906 // FIXME only one leader in the cluster should process
907 @Override
908 public void event(OpenstackRouterEvent event) {
909 switch (event.type()) {
910 case OPENSTACK_ROUTER_CREATED:
911 log.debug("Router(name:{}, ID:{}) is created",
912 event.subject().getName(),
913 event.subject().getId());
914 eventExecutor.execute(() -> routerUpdated(event.subject()));
915 break;
916 case OPENSTACK_ROUTER_UPDATED:
917 log.debug("Router(name:{}, ID:{}) is updated",
918 event.subject().getName(),
919 event.subject().getId());
920 eventExecutor.execute(() -> routerUpdated(event.subject()));
921 break;
922 case OPENSTACK_ROUTER_REMOVED:
923 log.debug("Router(name:{}, ID:{}) is removed",
924 event.subject().getName(),
925 event.subject().getId());
Frank Wang245a6822017-06-14 09:51:35 +0800926 eventExecutor.execute(() -> routerRemove(event.subject()));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900927 break;
928 case OPENSTACK_ROUTER_INTERFACE_ADDED:
929 log.debug("Router interface {} added to router {}",
930 event.routerIface().getPortId(),
931 event.routerIface().getId());
932 eventExecutor.execute(() -> routerIfaceAdded(
933 event.subject(),
934 event.routerIface()));
935 break;
936 case OPENSTACK_ROUTER_INTERFACE_UPDATED:
937 log.debug("Router interface {} on {} updated",
938 event.routerIface().getPortId(),
939 event.routerIface().getId());
940 break;
941 case OPENSTACK_ROUTER_INTERFACE_REMOVED:
942 log.debug("Router interface {} removed from router {}",
943 event.routerIface().getPortId(),
944 event.routerIface().getId());
945 eventExecutor.execute(() -> routerIfaceRemoved(
946 event.subject(),
947 event.routerIface()));
948 break;
949 case OPENSTACK_ROUTER_GATEWAY_ADDED:
daniel parkb5817102018-02-15 00:18:51 +0900950 log.debug("Router external gateway {} added", event.externalGateway().getNetworkId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900951 case OPENSTACK_ROUTER_GATEWAY_REMOVED:
daniel parkb5817102018-02-15 00:18:51 +0900952 log.debug("Router external gateway {} removed", event.externalGateway().getNetworkId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900953 case OPENSTACK_FLOATING_IP_CREATED:
954 case OPENSTACK_FLOATING_IP_UPDATED:
955 case OPENSTACK_FLOATING_IP_REMOVED:
956 case OPENSTACK_FLOATING_IP_ASSOCIATED:
957 case OPENSTACK_FLOATING_IP_DISASSOCIATED:
958 default:
959 // do nothing for the other events
960 break;
961 }
962 }
963 }
964
965 private class InternalNodeEventListener implements OpenstackNodeListener {
966
967 @Override
968 public boolean isRelevant(OpenstackNodeEvent event) {
969 // do not allow to proceed without leadership
970 NodeId leader = leadershipService.getLeader(appId.name());
971 return Objects.equals(localNodeId, leader);
972 }
973
974 @Override
975 public void event(OpenstackNodeEvent event) {
976 OpenstackNode osNode = event.subject();
977
978 switch (event.type()) {
Hyunsun Moon0d457362017-06-27 17:19:41 +0900979 case OPENSTACK_NODE_COMPLETE:
980 case OPENSTACK_NODE_INCOMPLETE:
Hyunsun Moon44aac662017-02-18 02:07:01 +0900981 eventExecutor.execute(() -> {
Hyunsun Moon0e058f22017-04-19 17:00:52 +0900982 log.info("Reconfigure routers for {}", osNode.hostname());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900983 reconfigureRouters();
984 });
985 break;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900986 case OPENSTACK_NODE_CREATED:
987 case OPENSTACK_NODE_UPDATED:
988 case OPENSTACK_NODE_REMOVED:
Hyunsun Moon44aac662017-02-18 02:07:01 +0900989 default:
990 break;
991 }
992 }
993
994 private void reconfigureRouters() {
995 osRouterService.routers().forEach(osRouter -> {
996 routerUpdated(osRouter);
997 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
998 routerIfaceAdded(osRouter, iface);
999 });
1000 });
1001 }
1002 }
sangho072c4dd2017-05-17 10:45:21 +09001003
1004 private class InternalInstancePortListener implements InstancePortListener {
1005
1006 @Override
1007 public boolean isRelevant(InstancePortEvent event) {
1008 InstancePort instPort = event.subject();
1009 return mastershipService.isLocalMaster(instPort.deviceId());
1010 }
1011
1012 @Override
1013 public void event(InstancePortEvent event) {
1014 InstancePort instPort = event.subject();
1015 switch (event.type()) {
1016 case OPENSTACK_INSTANCE_PORT_UPDATED:
1017 case OPENSTACK_INSTANCE_PORT_DETECTED:
1018 eventExecutor.execute(() -> {
1019 log.info("RoutingHandler: Instance port detected MAC:{} IP:{}",
1020 instPort.macAddress(),
1021 instPort.ipAddress());
1022 instPortDetected(event.subject());
1023 });
1024 break;
1025 case OPENSTACK_INSTANCE_PORT_VANISHED:
1026 eventExecutor.execute(() -> {
1027 log.info("RoutingHandler: Instance port vanished MAC:{} IP:{}",
1028 instPort.macAddress(),
1029 instPort.ipAddress());
1030 instPortRemoved(event.subject());
1031 });
1032 break;
1033 default:
1034 break;
1035 }
1036 }
1037
1038 private void instPortDetected(InstancePort instPort) {
1039 osNodeService.completeNodes(GATEWAY)
1040 .forEach(gwNode -> setRulesForSnatIngressRule(gwNode.intgBridge(),
1041 Long.parseLong(osNetworkService.network(instPort.networkId()).getProviderSegID()),
1042 IpPrefix.valueOf(instPort.ipAddress(), 32),
1043 instPort.deviceId(),
1044 true));
1045 }
1046
1047 private void instPortRemoved(InstancePort instPort) {
1048 osNodeService.completeNodes(GATEWAY)
1049 .forEach(gwNode -> setRulesForSnatIngressRule(gwNode.intgBridge(),
1050 Long.parseLong(osNetworkService.network(instPort.networkId()).getProviderSegID()),
1051 IpPrefix.valueOf(instPort.ipAddress(), 32),
1052 instPort.deviceId(),
1053 false));
1054 }
1055 }
Hyunsun Moon44aac662017-02-18 02:07:01 +09001056}