blob: 254dba95b24f02b77ed04fb6ed3c7a3cf84786eb [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;
97import static org.onosproject.openstacknetworking.impl.RulePopulatorUtil.buildExtension;
Hyunsun Moon0d457362017-06-27 17:19:41 +090098import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
99import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900100
101/**
102 * Handles OpenStack router events.
103 */
104@Component(immediate = true)
105public class OpenstackRoutingHandler {
106
107 private final Logger log = LoggerFactory.getLogger(getClass());
108
109 private static final String MSG_ENABLED = "Enabled ";
110 private static final String MSG_DISABLED = "Disabled ";
111 private static final String ERR_SET_FLOWS = "Failed to set flows for router %s:";
daniel parkee8700b2017-05-11 15:50:03 +0900112 private static final String ERR_UNSUPPORTED_NET_TYPE = "Unsupported network type";
sanghoe765ce22017-06-23 17:54:57 +0900113 private static final boolean USE_STATEFUL_SNAT = false;
114
115 @Property(name = "useStatefulSnat", boolValue = USE_STATEFUL_SNAT,
116 label = "Use Stateful SNAT for source NATing")
117 private boolean useStatefulSnat = USE_STATEFUL_SNAT;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900118
119 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
120 protected CoreService coreService;
121
122 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
123 protected LeadershipService leadershipService;
124
125 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
126 protected ClusterService clusterService;
127
128 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900129 protected OpenstackNodeService osNodeService;
130
131 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moon44aac662017-02-18 02:07:01 +0900132 protected OpenstackNetworkService osNetworkService;
133
134 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
135 protected OpenstackRouterService osRouterService;
136
daniel parkee8700b2017-05-11 15:50:03 +0900137 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sangho072c4dd2017-05-17 10:45:21 +0900138 protected InstancePortService instancePortService;
139
140 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
141 protected DeviceService deviceService;
142
143 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sanghodc375372017-06-08 10:41:30 +0900144 protected OpenstackFlowRuleService osFlowRuleService;
145
sangho072c4dd2017-05-17 10:45:21 +0900146 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
147 protected MastershipService mastershipService;
148
149 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
150 protected DriverService driverService;
151
sanghoe765ce22017-06-23 17:54:57 +0900152 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
153 protected ComponentConfigService configService;
154
Hyunsun Moon44aac662017-02-18 02:07:01 +0900155 private final ExecutorService eventExecutor = newSingleThreadScheduledExecutor(
156 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
157 private final OpenstackNodeListener osNodeListener = new InternalNodeEventListener();
158 private final OpenstackRouterListener osRouterListener = new InternalRouterEventListener();
sangho072c4dd2017-05-17 10:45:21 +0900159 private final InstancePortListener instancePortListener = new InternalInstancePortListener();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900160
161 private ApplicationId appId;
162 private NodeId localNodeId;
163
164 @Activate
165 protected void activate() {
166 appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
167 localNodeId = clusterService.getLocalNode().id();
168 leadershipService.runForLeadership(appId.name());
169 osNodeService.addListener(osNodeListener);
170 osRouterService.addListener(osRouterListener);
sangho072c4dd2017-05-17 10:45:21 +0900171 instancePortService.addListener(instancePortListener);
sanghoe765ce22017-06-23 17:54:57 +0900172 configService.registerProperties(getClass());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900173
174 log.info("Started");
175 }
176
177 @Deactivate
178 protected void deactivate() {
179 osRouterService.removeListener(osRouterListener);
180 osNodeService.removeListener(osNodeListener);
sangho072c4dd2017-05-17 10:45:21 +0900181 instancePortService.removeListener(instancePortListener);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900182 leadershipService.withdraw(appId.name());
sanghoe765ce22017-06-23 17:54:57 +0900183 configService.unregisterProperties(getClass(), false);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900184 eventExecutor.shutdown();
185
186 log.info("Stopped");
187 }
188
sanghoe765ce22017-06-23 17:54:57 +0900189 @Modified
190 protected void modified(ComponentContext context) {
191 Dictionary<?, ?> properties = context.getProperties();
192 Boolean flag;
193
194 flag = Tools.isPropertyEnabled(properties, "useStatefulSnat");
195 if (flag == null) {
196 log.info("useStatefulSnat is not configured, " +
197 "using current value of {}", useStatefulSnat);
198 } else {
199 useStatefulSnat = flag;
200 log.info("Configured. useStatefulSnat is {}",
201 useStatefulSnat ? "enabled" : "disabled");
202 }
203
204 resetSnatRules();
205 }
206
Hyunsun Moon44aac662017-02-18 02:07:01 +0900207 private void routerUpdated(Router osRouter) {
208 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
209 if (exGateway == null) {
210 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
sangho072c4dd2017-05-17 10:45:21 +0900211 setSourceNat(osRouter, iface, false);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900212 });
213 } else {
214 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
sangho072c4dd2017-05-17 10:45:21 +0900215 setSourceNat(osRouter, iface, exGateway.isEnableSnat());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900216 });
217 }
218 }
219
220 private void routerIfaceAdded(Router osRouter, RouterInterface osRouterIface) {
221 Subnet osSubnet = osNetworkService.subnet(osRouterIface.getSubnetId());
222 if (osSubnet == null) {
223 final String error = String.format(
224 ERR_SET_FLOWS + "subnet %s does not exist",
225 osRouterIface.getId(),
226 osRouterIface.getSubnetId());
227 throw new IllegalStateException(error);
228 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900229 setInternalRoutes(osRouter, osSubnet, true);
230 setGatewayIcmp(osSubnet, true);
231 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
232 if (exGateway != null && exGateway.isEnableSnat()) {
sangho072c4dd2017-05-17 10:45:21 +0900233 setSourceNat(osRouter, osRouterIface, true);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900234 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900235 log.info("Connected subnet({}) to {}", osSubnet.getCidr(), osRouter.getName());
236 }
237
238 private void routerIfaceRemoved(Router osRouter, RouterInterface osRouterIface) {
239 Subnet osSubnet = osNetworkService.subnet(osRouterIface.getSubnetId());
240 if (osSubnet == null) {
241 final String error = String.format(
242 ERR_SET_FLOWS + "subnet %s does not exist",
243 osRouterIface.getId(),
244 osRouterIface.getSubnetId());
245 throw new IllegalStateException(error);
246 }
247
248 setInternalRoutes(osRouter, osSubnet, false);
249 setGatewayIcmp(osSubnet, false);
250 ExternalGateway exGateway = osRouter.getExternalGatewayInfo();
251 if (exGateway != null && exGateway.isEnableSnat()) {
sangho072c4dd2017-05-17 10:45:21 +0900252 setSourceNat(osRouter, osRouterIface, false);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900253 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900254 log.info("Disconnected subnet({}) from {}", osSubnet.getCidr(), osRouter.getName());
255 }
256
sangho072c4dd2017-05-17 10:45:21 +0900257 private void setSourceNat(Router osRouter, RouterInterface routerIface, boolean install) {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900258 Subnet osSubnet = osNetworkService.subnet(routerIface.getSubnetId());
259 Network osNet = osNetworkService.network(osSubnet.getNetworkId());
260
Hyunsun Moon0d457362017-06-27 17:19:41 +0900261 osNodeService.completeNodes(COMPUTE).forEach(cNode -> {
262 setRulesToGateway(cNode, osNet.getProviderSegID(),
263 IpPrefix.valueOf(osSubnet.getCidr()), osNet.getNetworkType(),
264 install);
265 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900266
sanghoe765ce22017-06-23 17:54:57 +0900267 if (useStatefulSnat) {
268 setStatefulSnatRules(routerIface, install);
269 } else {
270 setReactiveSnatRules(routerIface, install);
271 }
272
273 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
274 log.info(updateStr + "external access for subnet({})", osSubnet.getCidr());
275 }
276
277 private void setStatefulSnatRules(RouterInterface routerIface, boolean install) {
278 Subnet osSubnet = osNetworkService.subnet(routerIface.getSubnetId());
279 Network osNet = osNetworkService.network(osSubnet.getNetworkId());
280
281 Optional<Router> osRouter = osRouterService.routers().stream()
282 .filter(router -> osRouterService.routerInterfaces(routerIface.getId()) != null)
283 .findAny();
284
285 if (!osRouter.isPresent()) {
286 log.error("Cannot find a router for router interface {} ", routerIface);
287 return;
288 }
289 IpAddress natAddress = getGatewayIpAddress(osRouter.get());
sangho072c4dd2017-05-17 10:45:21 +0900290 if (natAddress == null) {
291 return;
292 }
293 String netId = osNetworkService.subnet(routerIface.getSubnetId()).getNetworkId();
294
295 osNodeService.completeNodes(OpenstackNode.NodeType.GATEWAY)
296 .forEach(gwNode -> {
297 instancePortService.instancePorts(netId).stream()
298 .forEach(port -> setRulesForSnatIngressRule(gwNode.intgBridge(),
299 Long.parseLong(osNet.getProviderSegID()),
300 IpPrefix.valueOf(port.ipAddress(), 32),
301 port.deviceId(),
302 install));
303
304 setOvsNatIngressRule(gwNode.intgBridge(),
305 IpPrefix.valueOf(natAddress, 32),
306 Constants.DEFAULT_EXTERNAL_ROUTER_MAC, install);
307 setOvsNatEgressRule(gwNode.intgBridge(),
308 natAddress, Long.parseLong(osNet.getProviderSegID()),
309 gwNode.patchPortNum(), install);
310 });
sanghoe765ce22017-06-23 17:54:57 +0900311 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900312
sanghoe765ce22017-06-23 17:54:57 +0900313 private void setReactiveSnatRules(RouterInterface routerIface, boolean install) {
314 Subnet osSubnet = osNetworkService.subnet(routerIface.getSubnetId());
315 Network osNet = osNetworkService.network(osSubnet.getNetworkId());
316
317 osNodeService.completeNodes(GATEWAY)
318 .forEach(gwNode -> setRulesToController(
319 gwNode.intgBridge(),
320 osNet.getProviderSegID(),
321 IpPrefix.valueOf(osSubnet.getCidr()),
322 osNet.getNetworkType(),
323 install));
Hyunsun Moon44aac662017-02-18 02:07:01 +0900324 }
325
sangho072c4dd2017-05-17 10:45:21 +0900326 private IpAddress getGatewayIpAddress(Router osRouter) {
327
328 String extNetId = osNetworkService.network(osRouter.getExternalGatewayInfo().getNetworkId()).getId();
329 Optional<Subnet> extSubnet = osNetworkService.subnets().stream()
330 .filter(subnet -> subnet.getNetworkId().equals(extNetId))
331 .findAny();
332
333 if (!extSubnet.isPresent()) {
334 log.error("Cannot find externel subnet for the router");
335 return null;
336 }
337
338 return IpAddress.valueOf(extSubnet.get().getGateway());
339 }
340
sanghoe765ce22017-06-23 17:54:57 +0900341 private void resetSnatRules() {
342 if (useStatefulSnat) {
343 osRouterService.routerInterfaces().forEach(
344 routerIface -> {
345 setReactiveSnatRules(routerIface, false);
346 setStatefulSnatRules(routerIface, true);
347 }
348 );
349 } else {
350 osRouterService.routerInterfaces().forEach(
351 routerIface -> {
352 setStatefulSnatRules(routerIface, false);
353 setReactiveSnatRules(routerIface, true);
354 }
355 );
356 }
357 }
358
Hyunsun Moon44aac662017-02-18 02:07:01 +0900359 private void setGatewayIcmp(Subnet osSubnet, boolean install) {
360 if (Strings.isNullOrEmpty(osSubnet.getGateway())) {
361 // do nothing if no gateway is set
362 return;
363 }
364
365 // take ICMP request to a subnet gateway through gateway node group
366 Network network = osNetworkService.network(osSubnet.getNetworkId());
daniel parkee8700b2017-05-11 15:50:03 +0900367 switch (network.getNetworkType()) {
368 case VXLAN:
Hyunsun Moon0d457362017-06-27 17:19:41 +0900369 osNodeService.completeNodes(COMPUTE).stream()
370 .filter(cNode -> cNode.dataIp() != null)
371 .forEach(cNode -> setRulesToGatewayWithDstIp(
372 cNode,
373 cNode.gatewayGroupId(NetworkMode.VXLAN),
daniel parkee8700b2017-05-11 15:50:03 +0900374 network.getProviderSegID(),
375 IpAddress.valueOf(osSubnet.getGateway()),
376 NetworkMode.VXLAN,
377 install));
378 break;
379 case VLAN:
Hyunsun Moon0d457362017-06-27 17:19:41 +0900380 osNodeService.completeNodes(COMPUTE).stream()
381 .filter(cNode -> cNode.vlanPortNum() != null)
382 .forEach(cNode -> setRulesToGatewayWithDstIp(
383 cNode,
384 cNode.gatewayGroupId(NetworkMode.VLAN),
daniel parkee8700b2017-05-11 15:50:03 +0900385 network.getProviderSegID(),
386 IpAddress.valueOf(osSubnet.getGateway()),
387 NetworkMode.VLAN,
388 install));
389 break;
390 default:
391 final String error = String.format(
392 ERR_UNSUPPORTED_NET_TYPE + "%s",
393 network.getNetworkType().toString());
394 throw new IllegalStateException(error);
395 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900396
397 IpAddress gatewayIp = IpAddress.valueOf(osSubnet.getGateway());
Hyunsun Moon0d457362017-06-27 17:19:41 +0900398 osNodeService.completeNodes(GATEWAY).forEach(gNode -> {
399 setGatewayIcmpRule(
400 gatewayIp,
401 gNode.intgBridge(),
402 install
403 );
404 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900405
406 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
407 log.debug(updateStr + "ICMP to {}", osSubnet.getGateway());
408 }
409
410 private void setInternalRoutes(Router osRouter, Subnet updatedSubnet, boolean install) {
daniel parkee8700b2017-05-11 15:50:03 +0900411 Network updatedNetwork = osNetworkService.network(updatedSubnet.getNetworkId());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900412 Set<Subnet> routableSubnets = routableSubnets(osRouter, updatedSubnet.getId());
daniel parkee8700b2017-05-11 15:50:03 +0900413 String updatedSegmendId = getSegmentId(updatedSubnet);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900414
415 // installs rule from/to my subnet intentionally to fix ICMP failure
416 // to my subnet gateway if no external gateway added to the router
Hyunsun Moon0d457362017-06-27 17:19:41 +0900417 osNodeService.completeNodes(COMPUTE).forEach(cNode -> {
418 setInternalRouterRules(
419 cNode.intgBridge(),
420 updatedSegmendId,
421 updatedSegmendId,
422 IpPrefix.valueOf(updatedSubnet.getCidr()),
423 IpPrefix.valueOf(updatedSubnet.getCidr()),
424 updatedNetwork.getNetworkType(),
425 install
426 );
Hyunsun Moon44aac662017-02-18 02:07:01 +0900427
Hyunsun Moon0d457362017-06-27 17:19:41 +0900428 routableSubnets.forEach(subnet -> {
429 setInternalRouterRules(
430 cNode.intgBridge(),
431 updatedSegmendId,
432 getSegmentId(subnet),
433 IpPrefix.valueOf(updatedSubnet.getCidr()),
434 IpPrefix.valueOf(subnet.getCidr()),
435 updatedNetwork.getNetworkType(),
436 install
437 );
438 setInternalRouterRules(
439 cNode.intgBridge(),
440 getSegmentId(subnet),
441 updatedSegmendId,
442 IpPrefix.valueOf(subnet.getCidr()),
443 IpPrefix.valueOf(updatedSubnet.getCidr()),
444 updatedNetwork.getNetworkType(),
445 install
446 );
447 });
448 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900449
daniel parkee8700b2017-05-11 15:50:03 +0900450
Hyunsun Moon44aac662017-02-18 02:07:01 +0900451 final String updateStr = install ? MSG_ENABLED : MSG_DISABLED;
452 routableSubnets.forEach(subnet -> log.debug(
453 updateStr + "route between subnet:{} and subnet:{}",
454 subnet.getCidr(),
455 updatedSubnet.getCidr()));
456 }
457
458 private Set<Subnet> routableSubnets(Router osRouter, String osSubnetId) {
459 Set<Subnet> osSubnets = osRouterService.routerInterfaces(osRouter.getId())
460 .stream()
461 .filter(iface -> !Objects.equals(iface.getSubnetId(), osSubnetId))
462 .map(iface -> osNetworkService.subnet(iface.getSubnetId()))
463 .collect(Collectors.toSet());
464 return ImmutableSet.copyOf(osSubnets);
465 }
466
daniel parkee8700b2017-05-11 15:50:03 +0900467 private String getSegmentId(Subnet osSubnet) {
468 return osNetworkService.network(osSubnet.getNetworkId()).getProviderSegID();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900469 }
470
471 private void setGatewayIcmpRule(IpAddress gatewayIp, DeviceId deviceId, boolean install) {
472 TrafficSelector selector = DefaultTrafficSelector.builder()
473 .matchEthType(Ethernet.TYPE_IPV4)
474 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900475 .matchIPDst(gatewayIp.getIp4Address().toIpPrefix())
Hyunsun Moon44aac662017-02-18 02:07:01 +0900476 .build();
477
478 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
479 .setOutput(PortNumber.CONTROLLER)
480 .build();
481
sanghodc375372017-06-08 10:41:30 +0900482 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900483 appId,
484 deviceId,
485 selector,
486 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900487 PRIORITY_ICMP_RULE,
sanghodc375372017-06-08 10:41:30 +0900488 Constants.GW_COMMON_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900489 install);
490 }
491
daniel parkee8700b2017-05-11 15:50:03 +0900492 private void setInternalRouterRules(DeviceId deviceId, String srcSegmentId, String dstSegmentId,
493 IpPrefix srcSubnet, IpPrefix dstSubnet,
494 NetworkType networkType, boolean install) {
495 TrafficSelector selector;
496 TrafficTreatment treatment;
497 switch (networkType) {
498 case VXLAN:
499 selector = DefaultTrafficSelector.builder()
500 .matchEthType(Ethernet.TYPE_IPV4)
501 .matchTunnelId(Long.parseLong(srcSegmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900502 .matchIPSrc(srcSubnet.getIp4Prefix())
503 .matchIPDst(dstSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900504 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900505
daniel parkee8700b2017-05-11 15:50:03 +0900506 treatment = DefaultTrafficTreatment.builder()
507 .setTunnelId(Long.parseLong(dstSegmentId))
sanghodc375372017-06-08 10:41:30 +0900508 .transition(FORWARDING_TABLE)
daniel parkee8700b2017-05-11 15:50:03 +0900509 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900510
sanghodc375372017-06-08 10:41:30 +0900511 osFlowRuleService.setRule(
daniel parkee8700b2017-05-11 15:50:03 +0900512 appId,
513 deviceId,
514 selector,
515 treatment,
daniel parkee8700b2017-05-11 15:50:03 +0900516 PRIORITY_INTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900517 ROUTING_TABLE,
daniel parkee8700b2017-05-11 15:50:03 +0900518 install);
Hyunsun Moon44aac662017-02-18 02:07:01 +0900519
daniel parkee8700b2017-05-11 15:50:03 +0900520 selector = DefaultTrafficSelector.builder()
521 .matchEthType(Ethernet.TYPE_IPV4)
522 .matchTunnelId(Long.parseLong(dstSegmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900523 .matchIPSrc(srcSubnet.getIp4Prefix())
524 .matchIPDst(dstSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900525 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900526
daniel parkee8700b2017-05-11 15:50:03 +0900527 treatment = DefaultTrafficTreatment.builder()
528 .setTunnelId(Long.parseLong(dstSegmentId))
sanghodc375372017-06-08 10:41:30 +0900529 .transition(FORWARDING_TABLE)
daniel parkee8700b2017-05-11 15:50:03 +0900530 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900531
sanghodc375372017-06-08 10:41:30 +0900532 osFlowRuleService.setRule(
daniel parkee8700b2017-05-11 15:50:03 +0900533 appId,
534 deviceId,
535 selector,
536 treatment,
daniel parkee8700b2017-05-11 15:50:03 +0900537 PRIORITY_INTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900538 ROUTING_TABLE,
daniel parkee8700b2017-05-11 15:50:03 +0900539 install);
540 break;
541 case VLAN:
542 selector = DefaultTrafficSelector.builder()
543 .matchEthType(Ethernet.TYPE_IPV4)
544 .matchVlanId(VlanId.vlanId(srcSegmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900545 .matchIPSrc(srcSubnet.getIp4Prefix())
546 .matchIPDst(dstSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900547 .build();
548
549 treatment = DefaultTrafficTreatment.builder()
550 .setVlanId(VlanId.vlanId(dstSegmentId))
sanghodc375372017-06-08 10:41:30 +0900551 .transition(FORWARDING_TABLE)
daniel parkee8700b2017-05-11 15:50:03 +0900552 .build();
553
sanghodc375372017-06-08 10:41:30 +0900554 osFlowRuleService.setRule(
daniel parkee8700b2017-05-11 15:50:03 +0900555 appId,
556 deviceId,
557 selector,
558 treatment,
daniel parkee8700b2017-05-11 15:50:03 +0900559 PRIORITY_INTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900560 ROUTING_TABLE,
daniel parkee8700b2017-05-11 15:50:03 +0900561 install);
562
563 selector = DefaultTrafficSelector.builder()
564 .matchEthType(Ethernet.TYPE_IPV4)
565 .matchVlanId(VlanId.vlanId(dstSegmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900566 .matchIPSrc(srcSubnet.getIp4Prefix())
567 .matchIPDst(dstSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900568 .build();
569
570 treatment = DefaultTrafficTreatment.builder()
571 .setVlanId(VlanId.vlanId(dstSegmentId))
sanghodc375372017-06-08 10:41:30 +0900572 .transition(FORWARDING_TABLE)
daniel parkee8700b2017-05-11 15:50:03 +0900573 .build();
574
sanghodc375372017-06-08 10:41:30 +0900575 osFlowRuleService.setRule(
daniel parkee8700b2017-05-11 15:50:03 +0900576 appId,
577 deviceId,
578 selector,
579 treatment,
daniel parkee8700b2017-05-11 15:50:03 +0900580 PRIORITY_INTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900581 ROUTING_TABLE,
daniel parkee8700b2017-05-11 15:50:03 +0900582 install);
583 break;
584 default:
585 final String error = String.format(
586 ERR_UNSUPPORTED_NET_TYPE + "%s",
587 networkType.toString());
588 throw new IllegalStateException(error);
589 }
590
Hyunsun Moon44aac662017-02-18 02:07:01 +0900591 }
592
Hyunsun Moon0d457362017-06-27 17:19:41 +0900593 private void setRulesToGateway(OpenstackNode osNode, String segmentId, IpPrefix srcSubnet,
daniel parkee8700b2017-05-11 15:50:03 +0900594 NetworkType networkType, boolean install) {
595 TrafficTreatment treatment;
596 GroupId groupId;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900597
daniel parkee8700b2017-05-11 15:50:03 +0900598 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
599 .matchEthType(Ethernet.TYPE_IPV4)
Hyunsun Moon0d457362017-06-27 17:19:41 +0900600 .matchIPSrc(srcSubnet.getIp4Prefix())
daniel parkee8700b2017-05-11 15:50:03 +0900601 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
602
603 switch (networkType) {
604 case VXLAN:
605 sBuilder.matchTunnelId(Long.parseLong(segmentId));
Hyunsun Moon0d457362017-06-27 17:19:41 +0900606 groupId = osNode.gatewayGroupId(NetworkMode.VXLAN);
daniel parkee8700b2017-05-11 15:50:03 +0900607 break;
608 case VLAN:
609 sBuilder.matchVlanId(VlanId.vlanId(segmentId));
Hyunsun Moon0d457362017-06-27 17:19:41 +0900610 groupId = osNode.gatewayGroupId(NetworkMode.VLAN);
daniel parkee8700b2017-05-11 15:50:03 +0900611 break;
612 default:
613 final String error = String.format(
614 ERR_UNSUPPORTED_NET_TYPE + "%s",
615 networkType.toString());
616 throw new IllegalStateException(error);
617 }
618
619 treatment = DefaultTrafficTreatment.builder()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900620 .group(groupId)
621 .build();
622
sanghodc375372017-06-08 10:41:30 +0900623 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900624 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900625 osNode.intgBridge(),
daniel parkee8700b2017-05-11 15:50:03 +0900626 sBuilder.build(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900627 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900628 PRIORITY_EXTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900629 ROUTING_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900630 install);
631 }
632
sangho072c4dd2017-05-17 10:45:21 +0900633 private void setRulesForSnatIngressRule(DeviceId deviceId, Long vni, IpPrefix destVmIp,
634 DeviceId dstDeviceId, boolean install) {
635
636 TrafficSelector selector = DefaultTrafficSelector.builder()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900637 .matchEthType(Ethernet.TYPE_IPV4)
sangho072c4dd2017-05-17 10:45:21 +0900638 .matchIPDst(destVmIp)
639 .build();
Hyunsun Moon0d457362017-06-27 17:19:41 +0900640
sangho072c4dd2017-05-17 10:45:21 +0900641 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
642 .setTunnelId(vni)
643 .extension(buildExtension(
644 deviceService,
645 deviceId,
646 osNodeService.node(dstDeviceId).dataIp().getIp4Address()),
647 deviceId)
648 .setOutput(osNodeService.node(deviceId).tunnelPortNum())
649 .build();
daniel parkee8700b2017-05-11 15:50:03 +0900650
sanghodc375372017-06-08 10:41:30 +0900651 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900652 appId,
sangho072c4dd2017-05-17 10:45:21 +0900653 deviceId,
654 selector,
655 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900656 PRIORITY_EXTERNAL_ROUTING_RULE,
sanghodc375372017-06-08 10:41:30 +0900657 Constants.GW_COMMON_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900658 install);
659 }
660
Hyunsun Moon0d457362017-06-27 17:19:41 +0900661 private void setRulesToGatewayWithDstIp(OpenstackNode osNode, GroupId groupId,
662 String segmentId, IpAddress dstIp,
663 NetworkMode networkMode, boolean install) {
daniel parkee8700b2017-05-11 15:50:03 +0900664 TrafficSelector selector;
665 if (networkMode.equals(NetworkMode.VXLAN)) {
666 selector = DefaultTrafficSelector.builder()
667 .matchEthType(Ethernet.TYPE_IPV4)
668 .matchTunnelId(Long.valueOf(segmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900669 .matchIPDst(dstIp.getIp4Address().toIpPrefix())
daniel parkee8700b2017-05-11 15:50:03 +0900670 .build();
671 } else {
672 selector = DefaultTrafficSelector.builder()
673 .matchEthType(Ethernet.TYPE_IPV4)
674 .matchVlanId(VlanId.vlanId(segmentId))
Hyunsun Moon0d457362017-06-27 17:19:41 +0900675 .matchIPDst(dstIp.getIp4Address().toIpPrefix())
daniel parkee8700b2017-05-11 15:50:03 +0900676 .build();
677 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900678
679 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
680 .group(groupId)
681 .build();
682
sanghodc375372017-06-08 10:41:30 +0900683 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900684 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900685 osNode.intgBridge(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900686 selector,
687 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900688 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900689 ROUTING_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900690 install);
691 }
692
sangho072c4dd2017-05-17 10:45:21 +0900693 private void setOvsNatIngressRule(DeviceId deviceId, IpPrefix cidr, MacAddress dstMac, boolean install) {
694
695 TrafficSelector selector = DefaultTrafficSelector.builder()
696 .matchEthType(Ethernet.TYPE_IPV4)
697 .matchIPDst(cidr)
698 .build();
699
700 ExtensionTreatment natTreatment = RulePopulatorUtil.niciraConnTrackTreatmentBuilder(driverService, deviceId)
701 .commit(false)
702 .natAction(true)
703 .table((short) 0)
704 .build();
705
706 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
707 .setEthDst(dstMac)
708 .extension(natTreatment, deviceId)
709 .build();
710
711 osFlowRuleService.setRule(
712 appId,
713 deviceId,
714 selector,
715 treatment,
sanghoe765ce22017-06-23 17:54:57 +0900716 PRIORITY_STATEFUL_SNAT_RULE,
sangho072c4dd2017-05-17 10:45:21 +0900717 GW_COMMON_TABLE,
718 install);
719 }
720
721 private void setOvsNatEgressRule(DeviceId deviceId, IpAddress natAddress, long vni, PortNumber output,
722 boolean install) {
723
724 TrafficSelector selector = DefaultTrafficSelector.builder()
725 .matchEthType(Ethernet.TYPE_IPV4)
726 .matchEthDst(DEFAULT_GATEWAY_MAC)
727 .matchTunnelId(vni)
728 .build();
729
730 ExtensionTreatment natTreatment = RulePopulatorUtil.niciraConnTrackTreatmentBuilder(driverService, deviceId)
731 .commit(true)
732 .natAction(true)
733 .natIp(natAddress)
734 .build();
735
736 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
737 .extension(natTreatment, deviceId)
738 .setEthDst(DEFAULT_EXTERNAL_ROUTER_MAC)
739 .setEthSrc(DEFAULT_GATEWAY_MAC)
740 .setOutput(output)
741 .build();
742
743 osFlowRuleService.setRule(
744 appId,
745 deviceId,
746 selector,
747 treatment,
sanghoe765ce22017-06-23 17:54:57 +0900748 PRIORITY_STATEFUL_SNAT_RULE,
sangho072c4dd2017-05-17 10:45:21 +0900749 GW_COMMON_TABLE,
750 install);
751 }
752
sanghoe765ce22017-06-23 17:54:57 +0900753 private void setRulesToController(DeviceId deviceId, String segmentId, IpPrefix srcSubnet,
754 NetworkType networkType, boolean install) {
755 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
756 .matchEthType(Ethernet.TYPE_IPV4)
757 .matchIPSrc(srcSubnet);
758
759 switch (networkType) {
760 case VXLAN:
761 sBuilder.matchTunnelId(Long.parseLong(segmentId))
762 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
763 break;
764 case VLAN:
765 sBuilder.matchVlanId(VlanId.vlanId(segmentId))
766 .matchEthDst(osNodeService.node(deviceId).vlanPortMac());
767 break;
768 default:
769 final String error = String.format(
770 ERR_UNSUPPORTED_NET_TYPE + "%s",
771 networkType.toString());
772 throw new IllegalStateException(error);
773 }
774
775 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
776 .setEthDst(Constants.DEFAULT_GATEWAY_MAC);
777
778 if (networkType.equals(NetworkType.VLAN)) {
779 tBuilder.popVlan();
780 }
781
782 tBuilder.setOutput(PortNumber.CONTROLLER);
783
784 osFlowRuleService.setRule(
785 appId,
786 deviceId,
787 sBuilder.build(),
788 tBuilder.build(),
789 PRIORITY_EXTERNAL_ROUTING_RULE,
790 GW_COMMON_TABLE,
791 install);
792
793
794 // Sends ICMP response to controller for SNATing ingress traffic
795 TrafficSelector selector = DefaultTrafficSelector.builder()
796 .matchEthType(Ethernet.TYPE_IPV4)
797 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
798 .matchIcmpType(ICMP.TYPE_ECHO_REPLY)
799 .build();
800
801 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
802 .setOutput(PortNumber.CONTROLLER)
803 .build();
804
805 osFlowRuleService.setRule(
806 appId,
807 deviceId,
808 selector,
809 treatment,
810 PRIORITY_INTERNAL_ROUTING_RULE,
811 GW_COMMON_TABLE,
812 install);
813 }
sangho072c4dd2017-05-17 10:45:21 +0900814
Hyunsun Moon44aac662017-02-18 02:07:01 +0900815 private class InternalRouterEventListener implements OpenstackRouterListener {
816
817 @Override
818 public boolean isRelevant(OpenstackRouterEvent event) {
819 // do not allow to proceed without leadership
820 NodeId leader = leadershipService.getLeader(appId.name());
821 return Objects.equals(localNodeId, leader);
822 }
823
824 // FIXME only one leader in the cluster should process
825 @Override
826 public void event(OpenstackRouterEvent event) {
827 switch (event.type()) {
828 case OPENSTACK_ROUTER_CREATED:
829 log.debug("Router(name:{}, ID:{}) is created",
830 event.subject().getName(),
831 event.subject().getId());
832 eventExecutor.execute(() -> routerUpdated(event.subject()));
833 break;
834 case OPENSTACK_ROUTER_UPDATED:
835 log.debug("Router(name:{}, ID:{}) is updated",
836 event.subject().getName(),
837 event.subject().getId());
838 eventExecutor.execute(() -> routerUpdated(event.subject()));
839 break;
840 case OPENSTACK_ROUTER_REMOVED:
841 log.debug("Router(name:{}, ID:{}) is removed",
842 event.subject().getName(),
843 event.subject().getId());
844 break;
845 case OPENSTACK_ROUTER_INTERFACE_ADDED:
846 log.debug("Router interface {} added to router {}",
847 event.routerIface().getPortId(),
848 event.routerIface().getId());
849 eventExecutor.execute(() -> routerIfaceAdded(
850 event.subject(),
851 event.routerIface()));
852 break;
853 case OPENSTACK_ROUTER_INTERFACE_UPDATED:
854 log.debug("Router interface {} on {} updated",
855 event.routerIface().getPortId(),
856 event.routerIface().getId());
857 break;
858 case OPENSTACK_ROUTER_INTERFACE_REMOVED:
859 log.debug("Router interface {} removed from router {}",
860 event.routerIface().getPortId(),
861 event.routerIface().getId());
862 eventExecutor.execute(() -> routerIfaceRemoved(
863 event.subject(),
864 event.routerIface()));
865 break;
866 case OPENSTACK_ROUTER_GATEWAY_ADDED:
867 case OPENSTACK_ROUTER_GATEWAY_REMOVED:
868 case OPENSTACK_FLOATING_IP_CREATED:
869 case OPENSTACK_FLOATING_IP_UPDATED:
870 case OPENSTACK_FLOATING_IP_REMOVED:
871 case OPENSTACK_FLOATING_IP_ASSOCIATED:
872 case OPENSTACK_FLOATING_IP_DISASSOCIATED:
873 default:
874 // do nothing for the other events
875 break;
876 }
877 }
878 }
879
880 private class InternalNodeEventListener implements OpenstackNodeListener {
881
882 @Override
883 public boolean isRelevant(OpenstackNodeEvent event) {
884 // do not allow to proceed without leadership
885 NodeId leader = leadershipService.getLeader(appId.name());
886 return Objects.equals(localNodeId, leader);
887 }
888
889 @Override
890 public void event(OpenstackNodeEvent event) {
891 OpenstackNode osNode = event.subject();
892
893 switch (event.type()) {
Hyunsun Moon0d457362017-06-27 17:19:41 +0900894 case OPENSTACK_NODE_COMPLETE:
895 case OPENSTACK_NODE_INCOMPLETE:
Hyunsun Moon44aac662017-02-18 02:07:01 +0900896 eventExecutor.execute(() -> {
Hyunsun Moon0e058f22017-04-19 17:00:52 +0900897 log.info("Reconfigure routers for {}", osNode.hostname());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900898 reconfigureRouters();
899 });
900 break;
Hyunsun Moon0d457362017-06-27 17:19:41 +0900901 case OPENSTACK_NODE_CREATED:
902 case OPENSTACK_NODE_UPDATED:
903 case OPENSTACK_NODE_REMOVED:
Hyunsun Moon44aac662017-02-18 02:07:01 +0900904 default:
905 break;
906 }
907 }
908
909 private void reconfigureRouters() {
910 osRouterService.routers().forEach(osRouter -> {
911 routerUpdated(osRouter);
912 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
913 routerIfaceAdded(osRouter, iface);
914 });
915 });
916 }
917 }
sangho072c4dd2017-05-17 10:45:21 +0900918
919 private class InternalInstancePortListener implements InstancePortListener {
920
921 @Override
922 public boolean isRelevant(InstancePortEvent event) {
923 InstancePort instPort = event.subject();
924 return mastershipService.isLocalMaster(instPort.deviceId());
925 }
926
927 @Override
928 public void event(InstancePortEvent event) {
929 InstancePort instPort = event.subject();
930 switch (event.type()) {
931 case OPENSTACK_INSTANCE_PORT_UPDATED:
932 case OPENSTACK_INSTANCE_PORT_DETECTED:
933 eventExecutor.execute(() -> {
934 log.info("RoutingHandler: Instance port detected MAC:{} IP:{}",
935 instPort.macAddress(),
936 instPort.ipAddress());
937 instPortDetected(event.subject());
938 });
939 break;
940 case OPENSTACK_INSTANCE_PORT_VANISHED:
941 eventExecutor.execute(() -> {
942 log.info("RoutingHandler: Instance port vanished MAC:{} IP:{}",
943 instPort.macAddress(),
944 instPort.ipAddress());
945 instPortRemoved(event.subject());
946 });
947 break;
948 default:
949 break;
950 }
951 }
952
953 private void instPortDetected(InstancePort instPort) {
954 osNodeService.completeNodes(GATEWAY)
955 .forEach(gwNode -> setRulesForSnatIngressRule(gwNode.intgBridge(),
956 Long.parseLong(osNetworkService.network(instPort.networkId()).getProviderSegID()),
957 IpPrefix.valueOf(instPort.ipAddress(), 32),
958 instPort.deviceId(),
959 true));
960 }
961
962 private void instPortRemoved(InstancePort instPort) {
963 osNodeService.completeNodes(GATEWAY)
964 .forEach(gwNode -> setRulesForSnatIngressRule(gwNode.intgBridge(),
965 Long.parseLong(osNetworkService.network(instPort.networkId()).getProviderSegID()),
966 IpPrefix.valueOf(instPort.ipAddress(), 32),
967 instPort.deviceId(),
968 false));
969 }
970 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900971}