blob: 42a3da406022c285bf11c45deeedcfc25b5e5b63 [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;
daniel park576969a2018-03-09 07:07:41 +090052import org.onosproject.openstacknetworking.api.ExternalPeerRouter;
sangho072c4dd2017-05-17 10:45:21 +090053import org.onosproject.openstacknetworking.api.InstancePort;
54import org.onosproject.openstacknetworking.api.InstancePortEvent;
55import org.onosproject.openstacknetworking.api.InstancePortListener;
56import org.onosproject.openstacknetworking.api.InstancePortService;
sanghodc375372017-06-08 10:41:30 +090057import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090058import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
59import org.onosproject.openstacknetworking.api.OpenstackRouterEvent;
60import org.onosproject.openstacknetworking.api.OpenstackRouterListener;
61import org.onosproject.openstacknetworking.api.OpenstackRouterService;
Hyunsun Moon0d457362017-06-27 17:19:41 +090062import org.onosproject.openstacknode.api.OpenstackNode;
63import org.onosproject.openstacknode.api.OpenstackNode.NetworkMode;
64import org.onosproject.openstacknode.api.OpenstackNodeEvent;
65import org.onosproject.openstacknode.api.OpenstackNodeListener;
66import org.onosproject.openstacknode.api.OpenstackNodeService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090067import org.openstack4j.model.network.ExternalGateway;
68import org.openstack4j.model.network.Network;
daniel parkee8700b2017-05-11 15:50:03 +090069import org.openstack4j.model.network.NetworkType;
Hyunsun Moon44aac662017-02-18 02:07:01 +090070import org.openstack4j.model.network.Router;
71import org.openstack4j.model.network.RouterInterface;
72import org.openstack4j.model.network.Subnet;
sanghoe765ce22017-06-23 17:54:57 +090073import org.osgi.service.component.ComponentContext;
Hyunsun Moon44aac662017-02-18 02:07:01 +090074import org.slf4j.Logger;
75import org.slf4j.LoggerFactory;
76
sanghoe765ce22017-06-23 17:54:57 +090077import java.util.Dictionary;
Hyunsun Moon44aac662017-02-18 02:07:01 +090078import java.util.Objects;
sangho072c4dd2017-05-17 10:45:21 +090079import java.util.Optional;
Hyunsun Moon44aac662017-02-18 02:07:01 +090080import java.util.Set;
81import java.util.concurrent.ExecutorService;
82import java.util.stream.Collectors;
83
84import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
85import static org.onlab.util.Tools.groupedThreads;
sangho072c4dd2017-05-17 10:45:21 +090086import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_EXTERNAL_ROUTER_MAC;
87import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_GATEWAY_MAC;
88import static org.onosproject.openstacknetworking.api.Constants.FORWARDING_TABLE;
89import static org.onosproject.openstacknetworking.api.Constants.GW_COMMON_TABLE;
90import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
91import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_EXTERNAL_ROUTING_RULE;
92import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ICMP_RULE;
93import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_INTERNAL_ROUTING_RULE;
sanghoe765ce22017-06-23 17:54:57 +090094import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_STATEFUL_SNAT_RULE;
sangho072c4dd2017-05-17 10:45:21 +090095import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_SWITCHING_RULE;
96import static org.onosproject.openstacknetworking.api.Constants.ROUTING_TABLE;
Frank Wang245a6822017-06-14 09:51:35 +080097import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ADMIN_RULE;
sangho072c4dd2017-05-17 10:45:21 +090098import static org.onosproject.openstacknetworking.impl.RulePopulatorUtil.buildExtension;
Hyunsun Moon0d457362017-06-27 17:19:41 +090099import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
100import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900101
102/**
103 * Handles OpenStack router events.
104 */
105@Component(immediate = true)
106public class OpenstackRoutingHandler {
107
108 private final Logger log = LoggerFactory.getLogger(getClass());
109
110 private static final String MSG_ENABLED = "Enabled ";
111 private static final String MSG_DISABLED = "Disabled ";
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
daniel park576969a2018-03-09 07:07:41 +0900215
216 ExternalPeerRouter externalPeerRouter = osNetworkService.externalPeerRouter(exGateway);
217 VlanId vlanId = externalPeerRouter == null ? VlanId.NONE : externalPeerRouter.externalPeerRouterVlanId();
218
Hyunsun Moon44aac662017-02-18 02:07:01 +0900219 if (exGateway == null) {
daniel parkb5817102018-02-15 00:18:51 +0900220 osNetworkService.deleteExternalPeerRouter(exGateway);
daniel park576969a2018-03-09 07:07:41 +0900221 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> setSourceNat(iface, false));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900222 } else {
daniel park576969a2018-03-09 07:07:41 +0900223 osNetworkService.deriveExternalPeerRouterMac(exGateway, osRouter, vlanId);
224 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface ->
225 setSourceNat(iface, exGateway.isEnableSnat()));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900226 }
227 }
228
Frank Wang245a6822017-06-14 09:51:35 +0800229 private void routerRemove(Router osRouter) {
230 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
231 Network network = osNetworkService.network(osNetworkService.subnet(iface.getSubnetId())
232 .getNetworkId());
233 setRouterAdminRules(network.getProviderSegID(), network.getNetworkType(), false);
234 });
235 }
236
Hyunsun Moon44aac662017-02-18 02:07:01 +0900237 private void routerIfaceAdded(Router osRouter, RouterInterface osRouterIface) {
238 Subnet osSubnet = osNetworkService.subnet(osRouterIface.getSubnetId());
239 if (osSubnet == null) {
240 final String error = String.format(
Jian Li71670d12018-03-02 21:31:07 +0900241 "Failed to set flows for router %s: subnet %s does not exist",
Hyunsun Moon44aac662017-02-18 02:07:01 +0900242 osRouterIface.getId(),
243 osRouterIface.getSubnetId());
244 throw new IllegalStateException(error);
245 }
Frank Wang245a6822017-06-14 09:51:35 +0800246
247 if (!osRouter.isAdminStateUp()) {
248 Network network = osNetworkService.network(osSubnet.getNetworkId());
249 setRouterAdminRules(network.getProviderSegID(), network.getNetworkType(), true);
250 }
251
Hyunsun Moon44aac662017-02-18 02:07:01 +0900252 setInternalRoutes(osRouter, osSubnet, true);
253 setGatewayIcmp(osSubnet, true);
254 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
255 if (exGateway != null && exGateway.isEnableSnat()) {
daniel park576969a2018-03-09 07:07:41 +0900256 setSourceNat(osRouterIface, true);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900257 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900258 log.info("Connected subnet({}) to {}", osSubnet.getCidr(), osRouter.getName());
259 }
260
261 private void routerIfaceRemoved(Router osRouter, RouterInterface osRouterIface) {
262 Subnet osSubnet = osNetworkService.subnet(osRouterIface.getSubnetId());
263 if (osSubnet == null) {
264 final String error = String.format(
Jian Li71670d12018-03-02 21:31:07 +0900265 "Failed to set flows for router %s: subnet %s does not exist",
Hyunsun Moon44aac662017-02-18 02:07:01 +0900266 osRouterIface.getId(),
267 osRouterIface.getSubnetId());
268 throw new IllegalStateException(error);
269 }
270
Frank Wang245a6822017-06-14 09:51:35 +0800271 if (!osRouter.isAdminStateUp()) {
272 Network network = osNetworkService.network(osSubnet.getNetworkId());
273 setRouterAdminRules(network.getProviderSegID(), network.getNetworkType(), false);
274 }
275
Hyunsun Moon44aac662017-02-18 02:07:01 +0900276 setInternalRoutes(osRouter, osSubnet, false);
277 setGatewayIcmp(osSubnet, false);
278 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
279 if (exGateway != null && exGateway.isEnableSnat()) {
daniel park576969a2018-03-09 07:07:41 +0900280 setSourceNat(osRouterIface, false);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900281 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900282 log.info("Disconnected subnet({}) from {}", osSubnet.getCidr(), osRouter.getName());
283 }
284
daniel park576969a2018-03-09 07:07:41 +0900285 private void setSourceNat(RouterInterface routerIface, boolean install) {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900286 Subnet osSubnet = osNetworkService.subnet(routerIface.getSubnetId());
287 Network osNet = osNetworkService.network(osSubnet.getNetworkId());
288
Hyunsun Moon0d457362017-06-27 17:19:41 +0900289 osNodeService.completeNodes(COMPUTE).forEach(cNode -> {
290 setRulesToGateway(cNode, osNet.getProviderSegID(),
291 IpPrefix.valueOf(osSubnet.getCidr()), osNet.getNetworkType(),
292 install);
293 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900294
sanghoe765ce22017-06-23 17:54:57 +0900295 if (useStatefulSnat) {
296 setStatefulSnatRules(routerIface, install);
297 } else {
298 setReactiveSnatRules(routerIface, install);
299 }
300
301 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
302 log.info(updateStr + "external access for subnet({})", osSubnet.getCidr());
303 }
304
305 private void setStatefulSnatRules(RouterInterface routerIface, boolean install) {
306 Subnet osSubnet = osNetworkService.subnet(routerIface.getSubnetId());
307 Network osNet = osNetworkService.network(osSubnet.getNetworkId());
308
309 Optional<Router> osRouter = osRouterService.routers().stream()
310 .filter(router -> osRouterService.routerInterfaces(routerIface.getId()) != null)
311 .findAny();
312
313 if (!osRouter.isPresent()) {
314 log.error("Cannot find a router for router interface {} ", routerIface);
315 return;
316 }
317 IpAddress natAddress = getGatewayIpAddress(osRouter.get());
sangho072c4dd2017-05-17 10:45:21 +0900318 if (natAddress == null) {
319 return;
320 }
321 String netId = osNetworkService.subnet(routerIface.getSubnetId()).getNetworkId();
322
323 osNodeService.completeNodes(OpenstackNode.NodeType.GATEWAY)
324 .forEach(gwNode -> {
daniel park576969a2018-03-09 07:07:41 +0900325 instancePortService.instancePorts(netId)
326 .forEach(port -> setRulesForSnatIngressRule(gwNode.intgBridge(),
sangho072c4dd2017-05-17 10:45:21 +0900327 Long.parseLong(osNet.getProviderSegID()),
328 IpPrefix.valueOf(port.ipAddress(), 32),
329 port.deviceId(),
330 install));
331
332 setOvsNatIngressRule(gwNode.intgBridge(),
333 IpPrefix.valueOf(natAddress, 32),
334 Constants.DEFAULT_EXTERNAL_ROUTER_MAC, install);
335 setOvsNatEgressRule(gwNode.intgBridge(),
336 natAddress, Long.parseLong(osNet.getProviderSegID()),
337 gwNode.patchPortNum(), install);
338 });
sanghoe765ce22017-06-23 17:54:57 +0900339 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900340
sanghoe765ce22017-06-23 17:54:57 +0900341 private void setReactiveSnatRules(RouterInterface routerIface, boolean install) {
342 Subnet osSubnet = osNetworkService.subnet(routerIface.getSubnetId());
343 Network osNet = osNetworkService.network(osSubnet.getNetworkId());
344
345 osNodeService.completeNodes(GATEWAY)
346 .forEach(gwNode -> setRulesToController(
347 gwNode.intgBridge(),
348 osNet.getProviderSegID(),
349 IpPrefix.valueOf(osSubnet.getCidr()),
350 osNet.getNetworkType(),
351 install));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900352 }
353
sangho072c4dd2017-05-17 10:45:21 +0900354 private IpAddress getGatewayIpAddress(Router osRouter) {
355
356 String extNetId = osNetworkService.network(osRouter.getExternalGatewayInfo().getNetworkId()).getId();
357 Optional<Subnet> extSubnet = osNetworkService.subnets().stream()
358 .filter(subnet -> subnet.getNetworkId().equals(extNetId))
359 .findAny();
360
361 if (!extSubnet.isPresent()) {
362 log.error("Cannot find externel subnet for the router");
363 return null;
364 }
365
366 return IpAddress.valueOf(extSubnet.get().getGateway());
367 }
368
sanghoe765ce22017-06-23 17:54:57 +0900369 private void resetSnatRules() {
370 if (useStatefulSnat) {
371 osRouterService.routerInterfaces().forEach(
372 routerIface -> {
373 setReactiveSnatRules(routerIface, false);
374 setStatefulSnatRules(routerIface, true);
375 }
376 );
377 } else {
378 osRouterService.routerInterfaces().forEach(
379 routerIface -> {
380 setStatefulSnatRules(routerIface, false);
381 setReactiveSnatRules(routerIface, true);
382 }
383 );
384 }
385 }
386
Hyunsun Moon44aac662017-02-18 02:07:01 +0900387 private void setGatewayIcmp(Subnet osSubnet, boolean install) {
daniel parkb5817102018-02-15 00:18:51 +0900388 OpenstackNode sourceNatGateway = osNodeService.completeNodes(GATEWAY).stream().findFirst().orElse(null);
389
390 if (sourceNatGateway == null) {
391 return;
392 }
393
Hyunsun Moon44aac662017-02-18 02:07:01 +0900394 if (Strings.isNullOrEmpty(osSubnet.getGateway())) {
395 // do nothing if no gateway is set
396 return;
397 }
398
399 // take ICMP request to a subnet gateway through gateway node group
400 Network network = osNetworkService.network(osSubnet.getNetworkId());
daniel parkee8700b2017-05-11 15:50:03 +0900401 switch (network.getNetworkType()) {
402 case VXLAN:
Hyunsun Moon0d457362017-06-27 17:19:41 +0900403 osNodeService.completeNodes(COMPUTE).stream()
404 .filter(cNode -> cNode.dataIp() != null)
405 .forEach(cNode -> setRulesToGatewayWithDstIp(
406 cNode,
daniel parkb5817102018-02-15 00:18:51 +0900407 sourceNatGateway,
daniel parkee8700b2017-05-11 15:50:03 +0900408 network.getProviderSegID(),
409 IpAddress.valueOf(osSubnet.getGateway()),
410 NetworkMode.VXLAN,
411 install));
412 break;
413 case VLAN:
Hyunsun Moon0d457362017-06-27 17:19:41 +0900414 osNodeService.completeNodes(COMPUTE).stream()
415 .filter(cNode -> cNode.vlanPortNum() != null)
416 .forEach(cNode -> setRulesToGatewayWithDstIp(
417 cNode,
daniel parkb5817102018-02-15 00:18:51 +0900418 sourceNatGateway,
daniel parkee8700b2017-05-11 15:50:03 +0900419 network.getProviderSegID(),
420 IpAddress.valueOf(osSubnet.getGateway()),
421 NetworkMode.VLAN,
422 install));
423 break;
424 default:
Jian Li71670d12018-03-02 21:31:07 +0900425 final String error = String.format("%s %s",
426 ERR_UNSUPPORTED_NET_TYPE,
daniel parkee8700b2017-05-11 15:50:03 +0900427 network.getNetworkType().toString());
428 throw new IllegalStateException(error);
429 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900430
431 IpAddress gatewayIp = IpAddress.valueOf(osSubnet.getGateway());
daniel park576969a2018-03-09 07:07:41 +0900432 osNodeService.completeNodes(GATEWAY).forEach(gNode ->
Hyunsun Moon0d457362017-06-27 17:19:41 +0900433 setGatewayIcmpRule(
434 gatewayIp,
435 gNode.intgBridge(),
daniel park576969a2018-03-09 07:07:41 +0900436 install));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900437
438 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
439 log.debug(updateStr + "ICMP to {}", osSubnet.getGateway());
440 }
441
442 private void setInternalRoutes(Router osRouter, Subnet updatedSubnet, boolean install) {
daniel parkee8700b2017-05-11 15:50:03 +0900443 Network updatedNetwork = osNetworkService.network(updatedSubnet.getNetworkId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900444 Set<Subnet> routableSubnets = routableSubnets(osRouter, updatedSubnet.getId());
daniel parkee8700b2017-05-11 15:50:03 +0900445 String updatedSegmendId = getSegmentId(updatedSubnet);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900446
447 // installs rule from/to my subnet intentionally to fix ICMP failure
448 // to my subnet gateway if no external gateway added to the router
Hyunsun Moon0d457362017-06-27 17:19:41 +0900449 osNodeService.completeNodes(COMPUTE).forEach(cNode -> {
450 setInternalRouterRules(
451 cNode.intgBridge(),
452 updatedSegmendId,
453 updatedSegmendId,
454 IpPrefix.valueOf(updatedSubnet.getCidr()),
455 IpPrefix.valueOf(updatedSubnet.getCidr()),
456 updatedNetwork.getNetworkType(),
457 install
458 );
Hyunsun Moon44aac662017-02-18 02:07:01 +0900459
Hyunsun Moon0d457362017-06-27 17:19:41 +0900460 routableSubnets.forEach(subnet -> {
461 setInternalRouterRules(
462 cNode.intgBridge(),
463 updatedSegmendId,
464 getSegmentId(subnet),
465 IpPrefix.valueOf(updatedSubnet.getCidr()),
466 IpPrefix.valueOf(subnet.getCidr()),
467 updatedNetwork.getNetworkType(),
468 install
469 );
470 setInternalRouterRules(
471 cNode.intgBridge(),
472 getSegmentId(subnet),
473 updatedSegmendId,
474 IpPrefix.valueOf(subnet.getCidr()),
475 IpPrefix.valueOf(updatedSubnet.getCidr()),
476 updatedNetwork.getNetworkType(),
477 install
478 );
479 });
480 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900481
daniel parkee8700b2017-05-11 15:50:03 +0900482
Hyunsun Moon44aac662017-02-18 02:07:01 +0900483 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
484 routableSubnets.forEach(subnet -> log.debug(
485 updateStr + "route between subnet:{} and subnet:{}",
486 subnet.getCidr(),
487 updatedSubnet.getCidr()));
488 }
489
490 private Set<Subnet> routableSubnets(Router osRouter, String osSubnetId) {
491 Set<Subnet> osSubnets = osRouterService.routerInterfaces(osRouter.getId())
492 .stream()
493 .filter(iface -> !Objects.equals(iface.getSubnetId(), osSubnetId))
494 .map(iface -> osNetworkService.subnet(iface.getSubnetId()))
495 .collect(Collectors.toSet());
496 return ImmutableSet.copyOf(osSubnets);
497 }
498
daniel parkee8700b2017-05-11 15:50:03 +0900499 private String getSegmentId(Subnet osSubnet) {
500 return osNetworkService.network(osSubnet.getNetworkId()).getProviderSegID();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900501 }
502
503 private void setGatewayIcmpRule(IpAddress gatewayIp, DeviceId deviceId, boolean install) {
504 TrafficSelector selector = DefaultTrafficSelector.builder()
505 .matchEthType(Ethernet.TYPE_IPV4)
506 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900507 .matchIPDst(gatewayIp.getIp4Address().toIpPrefix())
Hyunsun Moon44aac662017-02-18 02:07:01 +0900508 .build();
509
510 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
511 .setOutput(PortNumber.CONTROLLER)
512 .build();
513
sanghodc375372017-06-08 10:41:30 +0900514 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900515 appId,
516 deviceId,
517 selector,
518 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900519 PRIORITY_ICMP_RULE,
sanghodc375372017-06-08 10:41:30 +0900520 Constants.GW_COMMON_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900521 install);
522 }
523
daniel parkee8700b2017-05-11 15:50:03 +0900524 private void setInternalRouterRules(DeviceId deviceId, String srcSegmentId, String dstSegmentId,
525 IpPrefix srcSubnet, IpPrefix dstSubnet,
526 NetworkType networkType, boolean install) {
527 TrafficSelector selector;
528 TrafficTreatment treatment;
529 switch (networkType) {
530 case VXLAN:
531 selector = DefaultTrafficSelector.builder()
532 .matchEthType(Ethernet.TYPE_IPV4)
533 .matchTunnelId(Long.parseLong(srcSegmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900534 .matchIPSrc(srcSubnet.getIp4Prefix())
535 .matchIPDst(dstSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900536 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900537
daniel parkee8700b2017-05-11 15:50:03 +0900538 treatment = DefaultTrafficTreatment.builder()
539 .setTunnelId(Long.parseLong(dstSegmentId))
sanghodc375372017-06-08 10:41:30 +0900540 .transition(FORWARDING_TABLE)
daniel parkee8700b2017-05-11 15:50:03 +0900541 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900542
sanghodc375372017-06-08 10:41:30 +0900543 osFlowRuleService.setRule(
daniel parkee8700b2017-05-11 15:50:03 +0900544 appId,
545 deviceId,
546 selector,
547 treatment,
daniel parkee8700b2017-05-11 15:50:03 +0900548 PRIORITY_INTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900549 ROUTING_TABLE,
daniel parkee8700b2017-05-11 15:50:03 +0900550 install);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900551
daniel parkee8700b2017-05-11 15:50:03 +0900552 selector = DefaultTrafficSelector.builder()
553 .matchEthType(Ethernet.TYPE_IPV4)
554 .matchTunnelId(Long.parseLong(dstSegmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900555 .matchIPSrc(srcSubnet.getIp4Prefix())
556 .matchIPDst(dstSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900557 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900558
daniel parkee8700b2017-05-11 15:50:03 +0900559 treatment = DefaultTrafficTreatment.builder()
560 .setTunnelId(Long.parseLong(dstSegmentId))
sanghodc375372017-06-08 10:41:30 +0900561 .transition(FORWARDING_TABLE)
daniel parkee8700b2017-05-11 15:50:03 +0900562 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900563
sanghodc375372017-06-08 10:41:30 +0900564 osFlowRuleService.setRule(
daniel parkee8700b2017-05-11 15:50:03 +0900565 appId,
566 deviceId,
567 selector,
568 treatment,
daniel parkee8700b2017-05-11 15:50:03 +0900569 PRIORITY_INTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900570 ROUTING_TABLE,
daniel parkee8700b2017-05-11 15:50:03 +0900571 install);
572 break;
573 case VLAN:
574 selector = DefaultTrafficSelector.builder()
575 .matchEthType(Ethernet.TYPE_IPV4)
576 .matchVlanId(VlanId.vlanId(srcSegmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900577 .matchIPSrc(srcSubnet.getIp4Prefix())
578 .matchIPDst(dstSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900579 .build();
580
581 treatment = DefaultTrafficTreatment.builder()
582 .setVlanId(VlanId.vlanId(dstSegmentId))
sanghodc375372017-06-08 10:41:30 +0900583 .transition(FORWARDING_TABLE)
daniel parkee8700b2017-05-11 15:50:03 +0900584 .build();
585
sanghodc375372017-06-08 10:41:30 +0900586 osFlowRuleService.setRule(
daniel parkee8700b2017-05-11 15:50:03 +0900587 appId,
588 deviceId,
589 selector,
590 treatment,
daniel parkee8700b2017-05-11 15:50:03 +0900591 PRIORITY_INTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900592 ROUTING_TABLE,
daniel parkee8700b2017-05-11 15:50:03 +0900593 install);
594
595 selector = DefaultTrafficSelector.builder()
596 .matchEthType(Ethernet.TYPE_IPV4)
597 .matchVlanId(VlanId.vlanId(dstSegmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900598 .matchIPSrc(srcSubnet.getIp4Prefix())
599 .matchIPDst(dstSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900600 .build();
601
602 treatment = DefaultTrafficTreatment.builder()
603 .setVlanId(VlanId.vlanId(dstSegmentId))
sanghodc375372017-06-08 10:41:30 +0900604 .transition(FORWARDING_TABLE)
daniel parkee8700b2017-05-11 15:50:03 +0900605 .build();
606
sanghodc375372017-06-08 10:41:30 +0900607 osFlowRuleService.setRule(
daniel parkee8700b2017-05-11 15:50:03 +0900608 appId,
609 deviceId,
610 selector,
611 treatment,
daniel parkee8700b2017-05-11 15:50:03 +0900612 PRIORITY_INTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900613 ROUTING_TABLE,
daniel parkee8700b2017-05-11 15:50:03 +0900614 install);
615 break;
616 default:
Jian Li71670d12018-03-02 21:31:07 +0900617 final String error = String.format("%s %s",
618 ERR_UNSUPPORTED_NET_TYPE,
daniel parkee8700b2017-05-11 15:50:03 +0900619 networkType.toString());
620 throw new IllegalStateException(error);
621 }
622
Hyunsun Moon44aac662017-02-18 02:07:01 +0900623 }
624
Hyunsun Moon0d457362017-06-27 17:19:41 +0900625 private void setRulesToGateway(OpenstackNode osNode, String segmentId, IpPrefix srcSubnet,
daniel parkee8700b2017-05-11 15:50:03 +0900626 NetworkType networkType, boolean install) {
627 TrafficTreatment treatment;
daniel parkb5817102018-02-15 00:18:51 +0900628 OpenstackNode sourceNatGateway = osNodeService.completeNodes(GATEWAY).stream().findFirst().orElse(null);
629
630 if (sourceNatGateway == null) {
631 return;
632 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900633
daniel parkee8700b2017-05-11 15:50:03 +0900634 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
635 .matchEthType(Ethernet.TYPE_IPV4)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900636 .matchIPSrc(srcSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900637 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
638
639 switch (networkType) {
640 case VXLAN:
641 sBuilder.matchTunnelId(Long.parseLong(segmentId));
daniel parkee8700b2017-05-11 15:50:03 +0900642 break;
643 case VLAN:
644 sBuilder.matchVlanId(VlanId.vlanId(segmentId));
daniel parkee8700b2017-05-11 15:50:03 +0900645 break;
646 default:
Jian Li71670d12018-03-02 21:31:07 +0900647 final String error = String.format("%s %s",
648 ERR_UNSUPPORTED_NET_TYPE,
daniel parkee8700b2017-05-11 15:50:03 +0900649 networkType.toString());
650 throw new IllegalStateException(error);
651 }
652
653 treatment = DefaultTrafficTreatment.builder()
daniel parkb5817102018-02-15 00:18:51 +0900654 .extension(buildExtension(
655 deviceService,
656 osNode.intgBridge(),
657 sourceNatGateway.dataIp().getIp4Address()),
658 osNode.intgBridge())
659 .setOutput(osNode.tunnelPortNum())
Hyunsun Moon44aac662017-02-18 02:07:01 +0900660 .build();
661
sanghodc375372017-06-08 10:41:30 +0900662 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900663 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900664 osNode.intgBridge(),
daniel parkee8700b2017-05-11 15:50:03 +0900665 sBuilder.build(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900666 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900667 PRIORITY_EXTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900668 ROUTING_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900669 install);
670 }
671
sangho072c4dd2017-05-17 10:45:21 +0900672 private void setRulesForSnatIngressRule(DeviceId deviceId, Long vni, IpPrefix destVmIp,
673 DeviceId dstDeviceId, boolean install) {
674
675 TrafficSelector selector = DefaultTrafficSelector.builder()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900676 .matchEthType(Ethernet.TYPE_IPV4)
sangho072c4dd2017-05-17 10:45:21 +0900677 .matchIPDst(destVmIp)
678 .build();
Hyunsun Moon0d457362017-06-27 17:19:41 +0900679
sangho072c4dd2017-05-17 10:45:21 +0900680 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
681 .setTunnelId(vni)
682 .extension(buildExtension(
683 deviceService,
684 deviceId,
685 osNodeService.node(dstDeviceId).dataIp().getIp4Address()),
686 deviceId)
687 .setOutput(osNodeService.node(deviceId).tunnelPortNum())
688 .build();
daniel parkee8700b2017-05-11 15:50:03 +0900689
sanghodc375372017-06-08 10:41:30 +0900690 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900691 appId,
sangho072c4dd2017-05-17 10:45:21 +0900692 deviceId,
693 selector,
694 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900695 PRIORITY_EXTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900696 Constants.GW_COMMON_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900697 install);
698 }
699
daniel parkb5817102018-02-15 00:18:51 +0900700 private void setRulesToGatewayWithDstIp(OpenstackNode osNode, OpenstackNode sourceNatGateway,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900701 String segmentId, IpAddress dstIp,
702 NetworkMode networkMode, boolean install) {
daniel parkee8700b2017-05-11 15:50:03 +0900703 TrafficSelector selector;
704 if (networkMode.equals(NetworkMode.VXLAN)) {
705 selector = DefaultTrafficSelector.builder()
706 .matchEthType(Ethernet.TYPE_IPV4)
707 .matchTunnelId(Long.valueOf(segmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900708 .matchIPDst(dstIp.getIp4Address().toIpPrefix())
daniel parkee8700b2017-05-11 15:50:03 +0900709 .build();
710 } else {
711 selector = DefaultTrafficSelector.builder()
712 .matchEthType(Ethernet.TYPE_IPV4)
713 .matchVlanId(VlanId.vlanId(segmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900714 .matchIPDst(dstIp.getIp4Address().toIpPrefix())
daniel parkee8700b2017-05-11 15:50:03 +0900715 .build();
716 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900717
718 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
daniel parkb5817102018-02-15 00:18:51 +0900719 .extension(buildExtension(
720 deviceService,
721 osNode.intgBridge(),
722 sourceNatGateway.dataIp().getIp4Address()),
723 osNode.intgBridge())
724 .setOutput(osNode.tunnelPortNum())
Hyunsun Moon44aac662017-02-18 02:07:01 +0900725 .build();
726
sanghodc375372017-06-08 10:41:30 +0900727 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900728 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900729 osNode.intgBridge(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900730 selector,
731 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900732 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900733 ROUTING_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900734 install);
735 }
736
sangho072c4dd2017-05-17 10:45:21 +0900737 private void setOvsNatIngressRule(DeviceId deviceId, IpPrefix cidr, MacAddress dstMac, boolean install) {
738
739 TrafficSelector selector = DefaultTrafficSelector.builder()
740 .matchEthType(Ethernet.TYPE_IPV4)
741 .matchIPDst(cidr)
742 .build();
743
744 ExtensionTreatment natTreatment = RulePopulatorUtil.niciraConnTrackTreatmentBuilder(driverService, deviceId)
745 .commit(false)
746 .natAction(true)
747 .table((short) 0)
748 .build();
749
750 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
751 .setEthDst(dstMac)
752 .extension(natTreatment, deviceId)
753 .build();
754
755 osFlowRuleService.setRule(
756 appId,
757 deviceId,
758 selector,
759 treatment,
sanghoe765ce22017-06-23 17:54:57 +0900760 PRIORITY_STATEFUL_SNAT_RULE,
sangho072c4dd2017-05-17 10:45:21 +0900761 GW_COMMON_TABLE,
762 install);
763 }
764
765 private void setOvsNatEgressRule(DeviceId deviceId, IpAddress natAddress, long vni, PortNumber output,
766 boolean install) {
767
768 TrafficSelector selector = DefaultTrafficSelector.builder()
769 .matchEthType(Ethernet.TYPE_IPV4)
770 .matchEthDst(DEFAULT_GATEWAY_MAC)
771 .matchTunnelId(vni)
772 .build();
773
774 ExtensionTreatment natTreatment = RulePopulatorUtil.niciraConnTrackTreatmentBuilder(driverService, deviceId)
775 .commit(true)
776 .natAction(true)
777 .natIp(natAddress)
778 .build();
779
780 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
781 .extension(natTreatment, deviceId)
782 .setEthDst(DEFAULT_EXTERNAL_ROUTER_MAC)
783 .setEthSrc(DEFAULT_GATEWAY_MAC)
784 .setOutput(output)
785 .build();
786
787 osFlowRuleService.setRule(
788 appId,
789 deviceId,
790 selector,
791 treatment,
sanghoe765ce22017-06-23 17:54:57 +0900792 PRIORITY_STATEFUL_SNAT_RULE,
sangho072c4dd2017-05-17 10:45:21 +0900793 GW_COMMON_TABLE,
794 install);
795 }
796
sanghoe765ce22017-06-23 17:54:57 +0900797 private void setRulesToController(DeviceId deviceId, String segmentId, IpPrefix srcSubnet,
798 NetworkType networkType, boolean install) {
799 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
800 .matchEthType(Ethernet.TYPE_IPV4)
801 .matchIPSrc(srcSubnet);
802
803 switch (networkType) {
804 case VXLAN:
805 sBuilder.matchTunnelId(Long.parseLong(segmentId))
806 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
807 break;
808 case VLAN:
809 sBuilder.matchVlanId(VlanId.vlanId(segmentId))
810 .matchEthDst(osNodeService.node(deviceId).vlanPortMac());
811 break;
812 default:
Jian Li71670d12018-03-02 21:31:07 +0900813 final String error = String.format("%s %s",
814 ERR_UNSUPPORTED_NET_TYPE,
sanghoe765ce22017-06-23 17:54:57 +0900815 networkType.toString());
816 throw new IllegalStateException(error);
817 }
818
819 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
820 .setEthDst(Constants.DEFAULT_GATEWAY_MAC);
821
822 if (networkType.equals(NetworkType.VLAN)) {
823 tBuilder.popVlan();
824 }
825
826 tBuilder.setOutput(PortNumber.CONTROLLER);
827
828 osFlowRuleService.setRule(
829 appId,
830 deviceId,
831 sBuilder.build(),
832 tBuilder.build(),
833 PRIORITY_EXTERNAL_ROUTING_RULE,
834 GW_COMMON_TABLE,
835 install);
836
837
838 // Sends ICMP response to controller for SNATing ingress traffic
839 TrafficSelector selector = DefaultTrafficSelector.builder()
840 .matchEthType(Ethernet.TYPE_IPV4)
841 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
842 .matchIcmpType(ICMP.TYPE_ECHO_REPLY)
843 .build();
844
845 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
846 .setOutput(PortNumber.CONTROLLER)
847 .build();
848
849 osFlowRuleService.setRule(
850 appId,
851 deviceId,
852 selector,
853 treatment,
854 PRIORITY_INTERNAL_ROUTING_RULE,
855 GW_COMMON_TABLE,
856 install);
857 }
sangho072c4dd2017-05-17 10:45:21 +0900858
Frank Wang245a6822017-06-14 09:51:35 +0800859 private void setRouterAdminRules(String segmentId, NetworkType networkType, boolean install) {
860 TrafficTreatment treatment;
861 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
862 .matchEthType(Ethernet.TYPE_IPV4);
863
864 switch (networkType) {
865 case VXLAN:
866 sBuilder.matchTunnelId(Long.parseLong(segmentId));
867 break;
868 case VLAN:
869 sBuilder.matchVlanId(VlanId.vlanId(segmentId));
870 break;
871 default:
Jian Li71670d12018-03-02 21:31:07 +0900872 final String error = String.format("%s %s",
873 ERR_UNSUPPORTED_NET_TYPE,
Frank Wang245a6822017-06-14 09:51:35 +0800874 networkType.toString());
875 throw new IllegalStateException(error);
876 }
877
878 treatment = DefaultTrafficTreatment.builder()
879 .drop()
880 .build();
881
882 osNodeService.completeNodes().stream()
883 .filter(osNode -> osNode.type() == COMPUTE)
884 .forEach(osNode -> {
885 osFlowRuleService.setRule(
886 appId,
887 osNode.intgBridge(),
888 sBuilder.build(),
889 treatment,
890 PRIORITY_ADMIN_RULE,
891 ROUTING_TABLE,
892 install);
893 });
894 }
895
Hyunsun Moon44aac662017-02-18 02:07:01 +0900896 private class InternalRouterEventListener implements OpenstackRouterListener {
897
898 @Override
899 public boolean isRelevant(OpenstackRouterEvent event) {
900 // do not allow to proceed without leadership
901 NodeId leader = leadershipService.getLeader(appId.name());
902 return Objects.equals(localNodeId, leader);
903 }
904
905 // FIXME only one leader in the cluster should process
906 @Override
907 public void event(OpenstackRouterEvent event) {
908 switch (event.type()) {
909 case OPENSTACK_ROUTER_CREATED:
910 log.debug("Router(name:{}, ID:{}) is created",
911 event.subject().getName(),
912 event.subject().getId());
913 eventExecutor.execute(() -> routerUpdated(event.subject()));
914 break;
915 case OPENSTACK_ROUTER_UPDATED:
916 log.debug("Router(name:{}, ID:{}) is updated",
917 event.subject().getName(),
918 event.subject().getId());
919 eventExecutor.execute(() -> routerUpdated(event.subject()));
920 break;
921 case OPENSTACK_ROUTER_REMOVED:
922 log.debug("Router(name:{}, ID:{}) is removed",
923 event.subject().getName(),
924 event.subject().getId());
Frank Wang245a6822017-06-14 09:51:35 +0800925 eventExecutor.execute(() -> routerRemove(event.subject()));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900926 break;
927 case OPENSTACK_ROUTER_INTERFACE_ADDED:
928 log.debug("Router interface {} added to router {}",
929 event.routerIface().getPortId(),
930 event.routerIface().getId());
931 eventExecutor.execute(() -> routerIfaceAdded(
932 event.subject(),
933 event.routerIface()));
934 break;
935 case OPENSTACK_ROUTER_INTERFACE_UPDATED:
936 log.debug("Router interface {} on {} updated",
937 event.routerIface().getPortId(),
938 event.routerIface().getId());
939 break;
940 case OPENSTACK_ROUTER_INTERFACE_REMOVED:
941 log.debug("Router interface {} removed from router {}",
942 event.routerIface().getPortId(),
943 event.routerIface().getId());
944 eventExecutor.execute(() -> routerIfaceRemoved(
945 event.subject(),
946 event.routerIface()));
947 break;
948 case OPENSTACK_ROUTER_GATEWAY_ADDED:
daniel parkb5817102018-02-15 00:18:51 +0900949 log.debug("Router external gateway {} added", event.externalGateway().getNetworkId());
Ray Milkey08932a72018-02-20 15:34:38 -0800950 break;
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());
Ray Milkey08932a72018-02-20 15:34:38 -0800953 break;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900954 case OPENSTACK_FLOATING_IP_CREATED:
955 case OPENSTACK_FLOATING_IP_UPDATED:
956 case OPENSTACK_FLOATING_IP_REMOVED:
957 case OPENSTACK_FLOATING_IP_ASSOCIATED:
958 case OPENSTACK_FLOATING_IP_DISASSOCIATED:
959 default:
960 // do nothing for the other events
961 break;
962 }
963 }
964 }
965
966 private class InternalNodeEventListener implements OpenstackNodeListener {
967
968 @Override
969 public boolean isRelevant(OpenstackNodeEvent event) {
970 // do not allow to proceed without leadership
971 NodeId leader = leadershipService.getLeader(appId.name());
972 return Objects.equals(localNodeId, leader);
973 }
974
975 @Override
976 public void event(OpenstackNodeEvent event) {
977 OpenstackNode osNode = event.subject();
978
979 switch (event.type()) {
Hyunsun Moon0d457362017-06-27 17:19:41 +0900980 case OPENSTACK_NODE_COMPLETE:
981 case OPENSTACK_NODE_INCOMPLETE:
Hyunsun Moon44aac662017-02-18 02:07:01 +0900982 eventExecutor.execute(() -> {
Hyunsun Moon0e058f22017-04-19 17:00:52 +0900983 log.info("Reconfigure routers for {}", osNode.hostname());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900984 reconfigureRouters();
985 });
986 break;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900987 case OPENSTACK_NODE_CREATED:
988 case OPENSTACK_NODE_UPDATED:
989 case OPENSTACK_NODE_REMOVED:
Hyunsun Moon44aac662017-02-18 02:07:01 +0900990 default:
991 break;
992 }
993 }
994
995 private void reconfigureRouters() {
996 osRouterService.routers().forEach(osRouter -> {
997 routerUpdated(osRouter);
998 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
999 routerIfaceAdded(osRouter, iface);
1000 });
1001 });
1002 }
1003 }
sangho072c4dd2017-05-17 10:45:21 +09001004
1005 private class InternalInstancePortListener implements InstancePortListener {
1006
1007 @Override
1008 public boolean isRelevant(InstancePortEvent event) {
1009 InstancePort instPort = event.subject();
1010 return mastershipService.isLocalMaster(instPort.deviceId());
1011 }
1012
1013 @Override
1014 public void event(InstancePortEvent event) {
1015 InstancePort instPort = event.subject();
1016 switch (event.type()) {
1017 case OPENSTACK_INSTANCE_PORT_UPDATED:
1018 case OPENSTACK_INSTANCE_PORT_DETECTED:
1019 eventExecutor.execute(() -> {
1020 log.info("RoutingHandler: Instance port detected MAC:{} IP:{}",
1021 instPort.macAddress(),
1022 instPort.ipAddress());
1023 instPortDetected(event.subject());
1024 });
1025 break;
1026 case OPENSTACK_INSTANCE_PORT_VANISHED:
1027 eventExecutor.execute(() -> {
1028 log.info("RoutingHandler: Instance port vanished MAC:{} IP:{}",
1029 instPort.macAddress(),
1030 instPort.ipAddress());
1031 instPortRemoved(event.subject());
1032 });
1033 break;
1034 default:
1035 break;
1036 }
1037 }
1038
1039 private void instPortDetected(InstancePort instPort) {
1040 osNodeService.completeNodes(GATEWAY)
1041 .forEach(gwNode -> setRulesForSnatIngressRule(gwNode.intgBridge(),
1042 Long.parseLong(osNetworkService.network(instPort.networkId()).getProviderSegID()),
1043 IpPrefix.valueOf(instPort.ipAddress(), 32),
1044 instPort.deviceId(),
1045 true));
1046 }
1047
1048 private void instPortRemoved(InstancePort instPort) {
1049 osNodeService.completeNodes(GATEWAY)
1050 .forEach(gwNode -> setRulesForSnatIngressRule(gwNode.intgBridge(),
1051 Long.parseLong(osNetworkService.network(instPort.networkId()).getProviderSegID()),
1052 IpPrefix.valueOf(instPort.ipAddress(), 32),
1053 instPort.deviceId(),
1054 false));
1055 }
1056 }
Hyunsun Moon44aac662017-02-18 02:07:01 +09001057}