blob: dd2e8875ad5e4a2bbcd15fb718814e26556af303 [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;
41import org.onosproject.core.GroupId;
sangho072c4dd2017-05-17 10:45:21 +090042import org.onosproject.mastership.MastershipService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090043import org.onosproject.net.DeviceId;
44import org.onosproject.net.PortNumber;
sangho072c4dd2017-05-17 10:45:21 +090045import org.onosproject.net.device.DeviceService;
46import org.onosproject.net.driver.DriverService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090047import org.onosproject.net.flow.DefaultTrafficSelector;
48import org.onosproject.net.flow.DefaultTrafficTreatment;
49import org.onosproject.net.flow.TrafficSelector;
50import org.onosproject.net.flow.TrafficTreatment;
sangho072c4dd2017-05-17 10:45:21 +090051import org.onosproject.net.flow.instructions.ExtensionTreatment;
Hyunsun Moon44aac662017-02-18 02:07:01 +090052import org.onosproject.openstacknetworking.api.Constants;
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 ";
112 private static final String ERR_SET_FLOWS = "Failed to set flows for router %s:";
daniel parkee8700b2017-05-11 15:50:03 +0900113 private static final String ERR_UNSUPPORTED_NET_TYPE = "Unsupported network type";
sanghoe765ce22017-06-23 17:54:57 +0900114 private static final boolean USE_STATEFUL_SNAT = false;
115
116 @Property(name = "useStatefulSnat", boolValue = USE_STATEFUL_SNAT,
117 label = "Use Stateful SNAT for source NATing")
118 private boolean useStatefulSnat = USE_STATEFUL_SNAT;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900119
120 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
121 protected CoreService coreService;
122
123 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
124 protected LeadershipService leadershipService;
125
126 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
127 protected ClusterService clusterService;
128
129 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900130 protected OpenstackNodeService osNodeService;
131
132 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900133 protected OpenstackNetworkService osNetworkService;
134
135 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
136 protected OpenstackRouterService osRouterService;
137
daniel parkee8700b2017-05-11 15:50:03 +0900138 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sangho072c4dd2017-05-17 10:45:21 +0900139 protected InstancePortService instancePortService;
140
141 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
142 protected DeviceService deviceService;
143
144 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sanghodc375372017-06-08 10:41:30 +0900145 protected OpenstackFlowRuleService osFlowRuleService;
146
sangho072c4dd2017-05-17 10:45:21 +0900147 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
148 protected MastershipService mastershipService;
149
150 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
151 protected DriverService driverService;
152
sanghoe765ce22017-06-23 17:54:57 +0900153 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
154 protected ComponentConfigService configService;
155
Hyunsun Moon44aac662017-02-18 02:07:01 +0900156 private final ExecutorService eventExecutor = newSingleThreadScheduledExecutor(
157 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
158 private final OpenstackNodeListener osNodeListener = new InternalNodeEventListener();
159 private final OpenstackRouterListener osRouterListener = new InternalRouterEventListener();
sangho072c4dd2017-05-17 10:45:21 +0900160 private final InstancePortListener instancePortListener = new InternalInstancePortListener();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900161
162 private ApplicationId appId;
163 private NodeId localNodeId;
164
165 @Activate
166 protected void activate() {
167 appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
168 localNodeId = clusterService.getLocalNode().id();
169 leadershipService.runForLeadership(appId.name());
170 osNodeService.addListener(osNodeListener);
171 osRouterService.addListener(osRouterListener);
sangho072c4dd2017-05-17 10:45:21 +0900172 instancePortService.addListener(instancePortListener);
sanghoe765ce22017-06-23 17:54:57 +0900173 configService.registerProperties(getClass());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900174
175 log.info("Started");
176 }
177
178 @Deactivate
179 protected void deactivate() {
180 osRouterService.removeListener(osRouterListener);
181 osNodeService.removeListener(osNodeListener);
sangho072c4dd2017-05-17 10:45:21 +0900182 instancePortService.removeListener(instancePortListener);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900183 leadershipService.withdraw(appId.name());
sanghoe765ce22017-06-23 17:54:57 +0900184 configService.unregisterProperties(getClass(), false);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900185 eventExecutor.shutdown();
186
187 log.info("Stopped");
188 }
189
sanghoe765ce22017-06-23 17:54:57 +0900190 @Modified
191 protected void modified(ComponentContext context) {
192 Dictionary<?, ?> properties = context.getProperties();
193 Boolean flag;
194
195 flag = Tools.isPropertyEnabled(properties, "useStatefulSnat");
196 if (flag == null) {
197 log.info("useStatefulSnat is not configured, " +
198 "using current value of {}", useStatefulSnat);
199 } else {
200 useStatefulSnat = flag;
201 log.info("Configured. useStatefulSnat is {}",
202 useStatefulSnat ? "enabled" : "disabled");
203 }
204
205 resetSnatRules();
206 }
207
Hyunsun Moon44aac662017-02-18 02:07:01 +0900208 private void routerUpdated(Router osRouter) {
209 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
Frank Wang245a6822017-06-14 09:51:35 +0800210
211 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
212 Network network = osNetworkService.network(osNetworkService.subnet(iface.getSubnetId())
213 .getNetworkId());
214 setRouterAdminRules(network.getProviderSegID(), network.getNetworkType(), !osRouter.isAdminStateUp());
215 });
216
Hyunsun Moon44aac662017-02-18 02:07:01 +0900217 if (exGateway == null) {
218 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
sangho072c4dd2017-05-17 10:45:21 +0900219 setSourceNat(osRouter, iface, false);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900220 });
221 } else {
222 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) {
387 if (Strings.isNullOrEmpty(osSubnet.getGateway())) {
388 // do nothing if no gateway is set
389 return;
390 }
391
392 // take ICMP request to a subnet gateway through gateway node group
393 Network network = osNetworkService.network(osSubnet.getNetworkId());
daniel parkee8700b2017-05-11 15:50:03 +0900394 switch (network.getNetworkType()) {
395 case VXLAN:
Hyunsun Moon0d457362017-06-27 17:19:41 +0900396 osNodeService.completeNodes(COMPUTE).stream()
397 .filter(cNode -> cNode.dataIp() != null)
398 .forEach(cNode -> setRulesToGatewayWithDstIp(
399 cNode,
400 cNode.gatewayGroupId(NetworkMode.VXLAN),
daniel parkee8700b2017-05-11 15:50:03 +0900401 network.getProviderSegID(),
402 IpAddress.valueOf(osSubnet.getGateway()),
403 NetworkMode.VXLAN,
404 install));
405 break;
406 case VLAN:
Hyunsun Moon0d457362017-06-27 17:19:41 +0900407 osNodeService.completeNodes(COMPUTE).stream()
408 .filter(cNode -> cNode.vlanPortNum() != null)
409 .forEach(cNode -> setRulesToGatewayWithDstIp(
410 cNode,
411 cNode.gatewayGroupId(NetworkMode.VLAN),
daniel parkee8700b2017-05-11 15:50:03 +0900412 network.getProviderSegID(),
413 IpAddress.valueOf(osSubnet.getGateway()),
414 NetworkMode.VLAN,
415 install));
416 break;
417 default:
418 final String error = String.format(
419 ERR_UNSUPPORTED_NET_TYPE + "%s",
420 network.getNetworkType().toString());
421 throw new IllegalStateException(error);
422 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900423
424 IpAddress gatewayIp = IpAddress.valueOf(osSubnet.getGateway());
Hyunsun Moon0d457362017-06-27 17:19:41 +0900425 osNodeService.completeNodes(GATEWAY).forEach(gNode -> {
426 setGatewayIcmpRule(
427 gatewayIp,
428 gNode.intgBridge(),
429 install
430 );
431 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900432
433 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
434 log.debug(updateStr + "ICMP to {}", osSubnet.getGateway());
435 }
436
437 private void setInternalRoutes(Router osRouter, Subnet updatedSubnet, boolean install) {
daniel parkee8700b2017-05-11 15:50:03 +0900438 Network updatedNetwork = osNetworkService.network(updatedSubnet.getNetworkId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900439 Set<Subnet> routableSubnets = routableSubnets(osRouter, updatedSubnet.getId());
daniel parkee8700b2017-05-11 15:50:03 +0900440 String updatedSegmendId = getSegmentId(updatedSubnet);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900441
442 // installs rule from/to my subnet intentionally to fix ICMP failure
443 // to my subnet gateway if no external gateway added to the router
Hyunsun Moon0d457362017-06-27 17:19:41 +0900444 osNodeService.completeNodes(COMPUTE).forEach(cNode -> {
445 setInternalRouterRules(
446 cNode.intgBridge(),
447 updatedSegmendId,
448 updatedSegmendId,
449 IpPrefix.valueOf(updatedSubnet.getCidr()),
450 IpPrefix.valueOf(updatedSubnet.getCidr()),
451 updatedNetwork.getNetworkType(),
452 install
453 );
Hyunsun Moon44aac662017-02-18 02:07:01 +0900454
Hyunsun Moon0d457362017-06-27 17:19:41 +0900455 routableSubnets.forEach(subnet -> {
456 setInternalRouterRules(
457 cNode.intgBridge(),
458 updatedSegmendId,
459 getSegmentId(subnet),
460 IpPrefix.valueOf(updatedSubnet.getCidr()),
461 IpPrefix.valueOf(subnet.getCidr()),
462 updatedNetwork.getNetworkType(),
463 install
464 );
465 setInternalRouterRules(
466 cNode.intgBridge(),
467 getSegmentId(subnet),
468 updatedSegmendId,
469 IpPrefix.valueOf(subnet.getCidr()),
470 IpPrefix.valueOf(updatedSubnet.getCidr()),
471 updatedNetwork.getNetworkType(),
472 install
473 );
474 });
475 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900476
daniel parkee8700b2017-05-11 15:50:03 +0900477
Hyunsun Moon44aac662017-02-18 02:07:01 +0900478 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
479 routableSubnets.forEach(subnet -> log.debug(
480 updateStr + "route between subnet:{} and subnet:{}",
481 subnet.getCidr(),
482 updatedSubnet.getCidr()));
483 }
484
485 private Set<Subnet> routableSubnets(Router osRouter, String osSubnetId) {
486 Set<Subnet> osSubnets = osRouterService.routerInterfaces(osRouter.getId())
487 .stream()
488 .filter(iface -> !Objects.equals(iface.getSubnetId(), osSubnetId))
489 .map(iface -> osNetworkService.subnet(iface.getSubnetId()))
490 .collect(Collectors.toSet());
491 return ImmutableSet.copyOf(osSubnets);
492 }
493
daniel parkee8700b2017-05-11 15:50:03 +0900494 private String getSegmentId(Subnet osSubnet) {
495 return osNetworkService.network(osSubnet.getNetworkId()).getProviderSegID();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900496 }
497
498 private void setGatewayIcmpRule(IpAddress gatewayIp, DeviceId deviceId, boolean install) {
499 TrafficSelector selector = DefaultTrafficSelector.builder()
500 .matchEthType(Ethernet.TYPE_IPV4)
501 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900502 .matchIPDst(gatewayIp.getIp4Address().toIpPrefix())
Hyunsun Moon44aac662017-02-18 02:07:01 +0900503 .build();
504
505 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
506 .setOutput(PortNumber.CONTROLLER)
507 .build();
508
sanghodc375372017-06-08 10:41:30 +0900509 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900510 appId,
511 deviceId,
512 selector,
513 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900514 PRIORITY_ICMP_RULE,
sanghodc375372017-06-08 10:41:30 +0900515 Constants.GW_COMMON_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900516 install);
517 }
518
daniel parkee8700b2017-05-11 15:50:03 +0900519 private void setInternalRouterRules(DeviceId deviceId, String srcSegmentId, String dstSegmentId,
520 IpPrefix srcSubnet, IpPrefix dstSubnet,
521 NetworkType networkType, boolean install) {
522 TrafficSelector selector;
523 TrafficTreatment treatment;
524 switch (networkType) {
525 case VXLAN:
526 selector = DefaultTrafficSelector.builder()
527 .matchEthType(Ethernet.TYPE_IPV4)
528 .matchTunnelId(Long.parseLong(srcSegmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900529 .matchIPSrc(srcSubnet.getIp4Prefix())
530 .matchIPDst(dstSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900531 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900532
daniel parkee8700b2017-05-11 15:50:03 +0900533 treatment = DefaultTrafficTreatment.builder()
534 .setTunnelId(Long.parseLong(dstSegmentId))
sanghodc375372017-06-08 10:41:30 +0900535 .transition(FORWARDING_TABLE)
daniel parkee8700b2017-05-11 15:50:03 +0900536 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900537
sanghodc375372017-06-08 10:41:30 +0900538 osFlowRuleService.setRule(
daniel parkee8700b2017-05-11 15:50:03 +0900539 appId,
540 deviceId,
541 selector,
542 treatment,
daniel parkee8700b2017-05-11 15:50:03 +0900543 PRIORITY_INTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900544 ROUTING_TABLE,
daniel parkee8700b2017-05-11 15:50:03 +0900545 install);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900546
daniel parkee8700b2017-05-11 15:50:03 +0900547 selector = DefaultTrafficSelector.builder()
548 .matchEthType(Ethernet.TYPE_IPV4)
549 .matchTunnelId(Long.parseLong(dstSegmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900550 .matchIPSrc(srcSubnet.getIp4Prefix())
551 .matchIPDst(dstSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900552 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900553
daniel parkee8700b2017-05-11 15:50:03 +0900554 treatment = DefaultTrafficTreatment.builder()
555 .setTunnelId(Long.parseLong(dstSegmentId))
sanghodc375372017-06-08 10:41:30 +0900556 .transition(FORWARDING_TABLE)
daniel parkee8700b2017-05-11 15:50:03 +0900557 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900558
sanghodc375372017-06-08 10:41:30 +0900559 osFlowRuleService.setRule(
daniel parkee8700b2017-05-11 15:50:03 +0900560 appId,
561 deviceId,
562 selector,
563 treatment,
daniel parkee8700b2017-05-11 15:50:03 +0900564 PRIORITY_INTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900565 ROUTING_TABLE,
daniel parkee8700b2017-05-11 15:50:03 +0900566 install);
567 break;
568 case VLAN:
569 selector = DefaultTrafficSelector.builder()
570 .matchEthType(Ethernet.TYPE_IPV4)
571 .matchVlanId(VlanId.vlanId(srcSegmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900572 .matchIPSrc(srcSubnet.getIp4Prefix())
573 .matchIPDst(dstSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900574 .build();
575
576 treatment = DefaultTrafficTreatment.builder()
577 .setVlanId(VlanId.vlanId(dstSegmentId))
sanghodc375372017-06-08 10:41:30 +0900578 .transition(FORWARDING_TABLE)
daniel parkee8700b2017-05-11 15:50:03 +0900579 .build();
580
sanghodc375372017-06-08 10:41:30 +0900581 osFlowRuleService.setRule(
daniel parkee8700b2017-05-11 15:50:03 +0900582 appId,
583 deviceId,
584 selector,
585 treatment,
daniel parkee8700b2017-05-11 15:50:03 +0900586 PRIORITY_INTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900587 ROUTING_TABLE,
daniel parkee8700b2017-05-11 15:50:03 +0900588 install);
589
590 selector = DefaultTrafficSelector.builder()
591 .matchEthType(Ethernet.TYPE_IPV4)
592 .matchVlanId(VlanId.vlanId(dstSegmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900593 .matchIPSrc(srcSubnet.getIp4Prefix())
594 .matchIPDst(dstSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900595 .build();
596
597 treatment = DefaultTrafficTreatment.builder()
598 .setVlanId(VlanId.vlanId(dstSegmentId))
sanghodc375372017-06-08 10:41:30 +0900599 .transition(FORWARDING_TABLE)
daniel parkee8700b2017-05-11 15:50:03 +0900600 .build();
601
sanghodc375372017-06-08 10:41:30 +0900602 osFlowRuleService.setRule(
daniel parkee8700b2017-05-11 15:50:03 +0900603 appId,
604 deviceId,
605 selector,
606 treatment,
daniel parkee8700b2017-05-11 15:50:03 +0900607 PRIORITY_INTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900608 ROUTING_TABLE,
daniel parkee8700b2017-05-11 15:50:03 +0900609 install);
610 break;
611 default:
612 final String error = String.format(
613 ERR_UNSUPPORTED_NET_TYPE + "%s",
614 networkType.toString());
615 throw new IllegalStateException(error);
616 }
617
Hyunsun Moon44aac662017-02-18 02:07:01 +0900618 }
619
Hyunsun Moon0d457362017-06-27 17:19:41 +0900620 private void setRulesToGateway(OpenstackNode osNode, String segmentId, IpPrefix srcSubnet,
daniel parkee8700b2017-05-11 15:50:03 +0900621 NetworkType networkType, boolean install) {
622 TrafficTreatment treatment;
623 GroupId groupId;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900624
daniel parkee8700b2017-05-11 15:50:03 +0900625 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
626 .matchEthType(Ethernet.TYPE_IPV4)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900627 .matchIPSrc(srcSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900628 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
629
630 switch (networkType) {
631 case VXLAN:
632 sBuilder.matchTunnelId(Long.parseLong(segmentId));
Hyunsun Moon0d457362017-06-27 17:19:41 +0900633 groupId = osNode.gatewayGroupId(NetworkMode.VXLAN);
daniel parkee8700b2017-05-11 15:50:03 +0900634 break;
635 case VLAN:
636 sBuilder.matchVlanId(VlanId.vlanId(segmentId));
Hyunsun Moon0d457362017-06-27 17:19:41 +0900637 groupId = osNode.gatewayGroupId(NetworkMode.VLAN);
daniel parkee8700b2017-05-11 15:50:03 +0900638 break;
639 default:
640 final String error = String.format(
641 ERR_UNSUPPORTED_NET_TYPE + "%s",
642 networkType.toString());
643 throw new IllegalStateException(error);
644 }
645
646 treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900647 .group(groupId)
648 .build();
649
sanghodc375372017-06-08 10:41:30 +0900650 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900651 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900652 osNode.intgBridge(),
daniel parkee8700b2017-05-11 15:50:03 +0900653 sBuilder.build(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900654 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900655 PRIORITY_EXTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900656 ROUTING_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900657 install);
658 }
659
sangho072c4dd2017-05-17 10:45:21 +0900660 private void setRulesForSnatIngressRule(DeviceId deviceId, Long vni, IpPrefix destVmIp,
661 DeviceId dstDeviceId, boolean install) {
662
663 TrafficSelector selector = DefaultTrafficSelector.builder()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900664 .matchEthType(Ethernet.TYPE_IPV4)
sangho072c4dd2017-05-17 10:45:21 +0900665 .matchIPDst(destVmIp)
666 .build();
Hyunsun Moon0d457362017-06-27 17:19:41 +0900667
sangho072c4dd2017-05-17 10:45:21 +0900668 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
669 .setTunnelId(vni)
670 .extension(buildExtension(
671 deviceService,
672 deviceId,
673 osNodeService.node(dstDeviceId).dataIp().getIp4Address()),
674 deviceId)
675 .setOutput(osNodeService.node(deviceId).tunnelPortNum())
676 .build();
daniel parkee8700b2017-05-11 15:50:03 +0900677
sanghodc375372017-06-08 10:41:30 +0900678 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900679 appId,
sangho072c4dd2017-05-17 10:45:21 +0900680 deviceId,
681 selector,
682 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900683 PRIORITY_EXTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900684 Constants.GW_COMMON_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900685 install);
686 }
687
Hyunsun Moon0d457362017-06-27 17:19:41 +0900688 private void setRulesToGatewayWithDstIp(OpenstackNode osNode, GroupId groupId,
689 String segmentId, IpAddress dstIp,
690 NetworkMode networkMode, boolean install) {
daniel parkee8700b2017-05-11 15:50:03 +0900691 TrafficSelector selector;
692 if (networkMode.equals(NetworkMode.VXLAN)) {
693 selector = DefaultTrafficSelector.builder()
694 .matchEthType(Ethernet.TYPE_IPV4)
695 .matchTunnelId(Long.valueOf(segmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900696 .matchIPDst(dstIp.getIp4Address().toIpPrefix())
daniel parkee8700b2017-05-11 15:50:03 +0900697 .build();
698 } else {
699 selector = DefaultTrafficSelector.builder()
700 .matchEthType(Ethernet.TYPE_IPV4)
701 .matchVlanId(VlanId.vlanId(segmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900702 .matchIPDst(dstIp.getIp4Address().toIpPrefix())
daniel parkee8700b2017-05-11 15:50:03 +0900703 .build();
704 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900705
706 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
707 .group(groupId)
708 .build();
709
sanghodc375372017-06-08 10:41:30 +0900710 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900711 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900712 osNode.intgBridge(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900713 selector,
714 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900715 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900716 ROUTING_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900717 install);
718 }
719
sangho072c4dd2017-05-17 10:45:21 +0900720 private void setOvsNatIngressRule(DeviceId deviceId, IpPrefix cidr, MacAddress dstMac, boolean install) {
721
722 TrafficSelector selector = DefaultTrafficSelector.builder()
723 .matchEthType(Ethernet.TYPE_IPV4)
724 .matchIPDst(cidr)
725 .build();
726
727 ExtensionTreatment natTreatment = RulePopulatorUtil.niciraConnTrackTreatmentBuilder(driverService, deviceId)
728 .commit(false)
729 .natAction(true)
730 .table((short) 0)
731 .build();
732
733 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
734 .setEthDst(dstMac)
735 .extension(natTreatment, deviceId)
736 .build();
737
738 osFlowRuleService.setRule(
739 appId,
740 deviceId,
741 selector,
742 treatment,
sanghoe765ce22017-06-23 17:54:57 +0900743 PRIORITY_STATEFUL_SNAT_RULE,
sangho072c4dd2017-05-17 10:45:21 +0900744 GW_COMMON_TABLE,
745 install);
746 }
747
748 private void setOvsNatEgressRule(DeviceId deviceId, IpAddress natAddress, long vni, PortNumber output,
749 boolean install) {
750
751 TrafficSelector selector = DefaultTrafficSelector.builder()
752 .matchEthType(Ethernet.TYPE_IPV4)
753 .matchEthDst(DEFAULT_GATEWAY_MAC)
754 .matchTunnelId(vni)
755 .build();
756
757 ExtensionTreatment natTreatment = RulePopulatorUtil.niciraConnTrackTreatmentBuilder(driverService, deviceId)
758 .commit(true)
759 .natAction(true)
760 .natIp(natAddress)
761 .build();
762
763 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
764 .extension(natTreatment, deviceId)
765 .setEthDst(DEFAULT_EXTERNAL_ROUTER_MAC)
766 .setEthSrc(DEFAULT_GATEWAY_MAC)
767 .setOutput(output)
768 .build();
769
770 osFlowRuleService.setRule(
771 appId,
772 deviceId,
773 selector,
774 treatment,
sanghoe765ce22017-06-23 17:54:57 +0900775 PRIORITY_STATEFUL_SNAT_RULE,
sangho072c4dd2017-05-17 10:45:21 +0900776 GW_COMMON_TABLE,
777 install);
778 }
779
sanghoe765ce22017-06-23 17:54:57 +0900780 private void setRulesToController(DeviceId deviceId, String segmentId, IpPrefix srcSubnet,
781 NetworkType networkType, boolean install) {
782 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
783 .matchEthType(Ethernet.TYPE_IPV4)
784 .matchIPSrc(srcSubnet);
785
786 switch (networkType) {
787 case VXLAN:
788 sBuilder.matchTunnelId(Long.parseLong(segmentId))
789 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
790 break;
791 case VLAN:
792 sBuilder.matchVlanId(VlanId.vlanId(segmentId))
793 .matchEthDst(osNodeService.node(deviceId).vlanPortMac());
794 break;
795 default:
796 final String error = String.format(
797 ERR_UNSUPPORTED_NET_TYPE + "%s",
798 networkType.toString());
799 throw new IllegalStateException(error);
800 }
801
802 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
803 .setEthDst(Constants.DEFAULT_GATEWAY_MAC);
804
805 if (networkType.equals(NetworkType.VLAN)) {
806 tBuilder.popVlan();
807 }
808
809 tBuilder.setOutput(PortNumber.CONTROLLER);
810
811 osFlowRuleService.setRule(
812 appId,
813 deviceId,
814 sBuilder.build(),
815 tBuilder.build(),
816 PRIORITY_EXTERNAL_ROUTING_RULE,
817 GW_COMMON_TABLE,
818 install);
819
820
821 // Sends ICMP response to controller for SNATing ingress traffic
822 TrafficSelector selector = DefaultTrafficSelector.builder()
823 .matchEthType(Ethernet.TYPE_IPV4)
824 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
825 .matchIcmpType(ICMP.TYPE_ECHO_REPLY)
826 .build();
827
828 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
829 .setOutput(PortNumber.CONTROLLER)
830 .build();
831
832 osFlowRuleService.setRule(
833 appId,
834 deviceId,
835 selector,
836 treatment,
837 PRIORITY_INTERNAL_ROUTING_RULE,
838 GW_COMMON_TABLE,
839 install);
840 }
sangho072c4dd2017-05-17 10:45:21 +0900841
Frank Wang245a6822017-06-14 09:51:35 +0800842 private void setRouterAdminRules(String segmentId, NetworkType networkType, boolean install) {
843 TrafficTreatment treatment;
844 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
845 .matchEthType(Ethernet.TYPE_IPV4);
846
847 switch (networkType) {
848 case VXLAN:
849 sBuilder.matchTunnelId(Long.parseLong(segmentId));
850 break;
851 case VLAN:
852 sBuilder.matchVlanId(VlanId.vlanId(segmentId));
853 break;
854 default:
855 final String error = String.format(
856 ERR_UNSUPPORTED_NET_TYPE + "%s",
857 networkType.toString());
858 throw new IllegalStateException(error);
859 }
860
861 treatment = DefaultTrafficTreatment.builder()
862 .drop()
863 .build();
864
865 osNodeService.completeNodes().stream()
866 .filter(osNode -> osNode.type() == COMPUTE)
867 .forEach(osNode -> {
868 osFlowRuleService.setRule(
869 appId,
870 osNode.intgBridge(),
871 sBuilder.build(),
872 treatment,
873 PRIORITY_ADMIN_RULE,
874 ROUTING_TABLE,
875 install);
876 });
877 }
878
Hyunsun Moon44aac662017-02-18 02:07:01 +0900879 private class InternalRouterEventListener implements OpenstackRouterListener {
880
881 @Override
882 public boolean isRelevant(OpenstackRouterEvent event) {
883 // do not allow to proceed without leadership
884 NodeId leader = leadershipService.getLeader(appId.name());
885 return Objects.equals(localNodeId, leader);
886 }
887
888 // FIXME only one leader in the cluster should process
889 @Override
890 public void event(OpenstackRouterEvent event) {
891 switch (event.type()) {
892 case OPENSTACK_ROUTER_CREATED:
893 log.debug("Router(name:{}, ID:{}) is created",
894 event.subject().getName(),
895 event.subject().getId());
896 eventExecutor.execute(() -> routerUpdated(event.subject()));
897 break;
898 case OPENSTACK_ROUTER_UPDATED:
899 log.debug("Router(name:{}, ID:{}) is updated",
900 event.subject().getName(),
901 event.subject().getId());
902 eventExecutor.execute(() -> routerUpdated(event.subject()));
903 break;
904 case OPENSTACK_ROUTER_REMOVED:
905 log.debug("Router(name:{}, ID:{}) is removed",
906 event.subject().getName(),
907 event.subject().getId());
Frank Wang245a6822017-06-14 09:51:35 +0800908 eventExecutor.execute(() -> routerRemove(event.subject()));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900909 break;
910 case OPENSTACK_ROUTER_INTERFACE_ADDED:
911 log.debug("Router interface {} added to router {}",
912 event.routerIface().getPortId(),
913 event.routerIface().getId());
914 eventExecutor.execute(() -> routerIfaceAdded(
915 event.subject(),
916 event.routerIface()));
917 break;
918 case OPENSTACK_ROUTER_INTERFACE_UPDATED:
919 log.debug("Router interface {} on {} updated",
920 event.routerIface().getPortId(),
921 event.routerIface().getId());
922 break;
923 case OPENSTACK_ROUTER_INTERFACE_REMOVED:
924 log.debug("Router interface {} removed from router {}",
925 event.routerIface().getPortId(),
926 event.routerIface().getId());
927 eventExecutor.execute(() -> routerIfaceRemoved(
928 event.subject(),
929 event.routerIface()));
930 break;
931 case OPENSTACK_ROUTER_GATEWAY_ADDED:
932 case OPENSTACK_ROUTER_GATEWAY_REMOVED:
933 case OPENSTACK_FLOATING_IP_CREATED:
934 case OPENSTACK_FLOATING_IP_UPDATED:
935 case OPENSTACK_FLOATING_IP_REMOVED:
936 case OPENSTACK_FLOATING_IP_ASSOCIATED:
937 case OPENSTACK_FLOATING_IP_DISASSOCIATED:
938 default:
939 // do nothing for the other events
940 break;
941 }
942 }
943 }
944
945 private class InternalNodeEventListener implements OpenstackNodeListener {
946
947 @Override
948 public boolean isRelevant(OpenstackNodeEvent event) {
949 // do not allow to proceed without leadership
950 NodeId leader = leadershipService.getLeader(appId.name());
951 return Objects.equals(localNodeId, leader);
952 }
953
954 @Override
955 public void event(OpenstackNodeEvent event) {
956 OpenstackNode osNode = event.subject();
957
958 switch (event.type()) {
Hyunsun Moon0d457362017-06-27 17:19:41 +0900959 case OPENSTACK_NODE_COMPLETE:
960 case OPENSTACK_NODE_INCOMPLETE:
Hyunsun Moon44aac662017-02-18 02:07:01 +0900961 eventExecutor.execute(() -> {
Hyunsun Moon0e058f22017-04-19 17:00:52 +0900962 log.info("Reconfigure routers for {}", osNode.hostname());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900963 reconfigureRouters();
964 });
965 break;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900966 case OPENSTACK_NODE_CREATED:
967 case OPENSTACK_NODE_UPDATED:
968 case OPENSTACK_NODE_REMOVED:
Hyunsun Moon44aac662017-02-18 02:07:01 +0900969 default:
970 break;
971 }
972 }
973
974 private void reconfigureRouters() {
975 osRouterService.routers().forEach(osRouter -> {
976 routerUpdated(osRouter);
977 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
978 routerIfaceAdded(osRouter, iface);
979 });
980 });
981 }
982 }
sangho072c4dd2017-05-17 10:45:21 +0900983
984 private class InternalInstancePortListener implements InstancePortListener {
985
986 @Override
987 public boolean isRelevant(InstancePortEvent event) {
988 InstancePort instPort = event.subject();
989 return mastershipService.isLocalMaster(instPort.deviceId());
990 }
991
992 @Override
993 public void event(InstancePortEvent event) {
994 InstancePort instPort = event.subject();
995 switch (event.type()) {
996 case OPENSTACK_INSTANCE_PORT_UPDATED:
997 case OPENSTACK_INSTANCE_PORT_DETECTED:
998 eventExecutor.execute(() -> {
999 log.info("RoutingHandler: Instance port detected MAC:{} IP:{}",
1000 instPort.macAddress(),
1001 instPort.ipAddress());
1002 instPortDetected(event.subject());
1003 });
1004 break;
1005 case OPENSTACK_INSTANCE_PORT_VANISHED:
1006 eventExecutor.execute(() -> {
1007 log.info("RoutingHandler: Instance port vanished MAC:{} IP:{}",
1008 instPort.macAddress(),
1009 instPort.ipAddress());
1010 instPortRemoved(event.subject());
1011 });
1012 break;
1013 default:
1014 break;
1015 }
1016 }
1017
1018 private void instPortDetected(InstancePort instPort) {
1019 osNodeService.completeNodes(GATEWAY)
1020 .forEach(gwNode -> setRulesForSnatIngressRule(gwNode.intgBridge(),
1021 Long.parseLong(osNetworkService.network(instPort.networkId()).getProviderSegID()),
1022 IpPrefix.valueOf(instPort.ipAddress(), 32),
1023 instPort.deviceId(),
1024 true));
1025 }
1026
1027 private void instPortRemoved(InstancePort instPort) {
1028 osNodeService.completeNodes(GATEWAY)
1029 .forEach(gwNode -> setRulesForSnatIngressRule(gwNode.intgBridge(),
1030 Long.parseLong(osNetworkService.network(instPort.networkId()).getProviderSegID()),
1031 IpPrefix.valueOf(instPort.ipAddress(), 32),
1032 instPort.deviceId(),
1033 false));
1034 }
1035 }
Hyunsun Moon44aac662017-02-18 02:07:01 +09001036}