blob: 970a3312ded09396ee01307f7a451b45c985a749 [file] [log] [blame]
sangho0c2a3da2016-02-16 13:39:07 +09001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
sangho0c2a3da2016-02-16 13:39:07 +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.routing;
17
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070018import com.google.common.collect.ImmutableSet;
sangho0c2a3da2016-02-16 13:39:07 +090019import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
24import org.apache.felix.scr.annotations.Service;
25import org.onlab.packet.Ethernet;
sangho0c2a3da2016-02-16 13:39:07 +090026import org.onlab.packet.Ip4Address;
27import org.onlab.packet.MacAddress;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070028import org.onlab.util.Tools;
sangho0c2a3da2016-02-16 13:39:07 +090029import org.onosproject.core.ApplicationId;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070030import org.onosproject.core.GroupId;
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090031import org.onosproject.net.DeviceId;
sangho6032f342016-07-07 14:32:03 +090032import org.onosproject.net.Host;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070033import org.onosproject.net.PortNumber;
sangho0c2a3da2016-02-16 13:39:07 +090034import org.onosproject.net.device.DeviceService;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070035import org.onosproject.net.flow.DefaultTrafficSelector;
36import org.onosproject.net.flow.DefaultTrafficTreatment;
37import org.onosproject.net.flow.TrafficSelector;
38import org.onosproject.net.flow.TrafficTreatment;
39import org.onosproject.net.flowobjective.DefaultForwardingObjective;
sangho0c2a3da2016-02-16 13:39:07 +090040import org.onosproject.net.flowobjective.FlowObjectiveService;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070041import org.onosproject.net.flowobjective.ForwardingObjective;
sangho93447f12016-02-24 00:33:22 +090042import org.onosproject.openstackinterface.OpenstackInterfaceService;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070043import org.onosproject.openstackinterface.OpenstackNetwork;
sangho93447f12016-02-24 00:33:22 +090044import org.onosproject.openstackinterface.OpenstackPort;
45import org.onosproject.openstackinterface.OpenstackRouter;
46import org.onosproject.openstackinterface.OpenstackRouterInterface;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070047import org.onosproject.openstackinterface.OpenstackSubnet;
48import org.onosproject.openstacknetworking.AbstractVmHandler;
sangho6032f342016-07-07 14:32:03 +090049import org.onosproject.openstacknetworking.Constants;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070050import org.onosproject.openstacknetworking.OpenstackRoutingService;
51import org.onosproject.openstacknetworking.RulePopulatorUtil;
sangho6032f342016-07-07 14:32:03 +090052import org.onosproject.openstacknode.OpenstackNode;
53import org.onosproject.openstacknode.OpenstackNodeEvent;
54import org.onosproject.openstacknode.OpenstackNodeListener;
55import org.onosproject.openstacknode.OpenstackNodeService;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070056import org.onosproject.scalablegateway.api.GatewayNode;
57import org.onosproject.scalablegateway.api.ScalableGatewayService;
sangho0c2a3da2016-02-16 13:39:07 +090058import org.slf4j.Logger;
59import org.slf4j.LoggerFactory;
60
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070061import java.util.Objects;
Daniel Park23193902016-03-24 18:17:19 +090062import java.util.Optional;
sangho6032f342016-07-07 14:32:03 +090063import java.util.Set;
sangho0c2a3da2016-02-16 13:39:07 +090064import java.util.concurrent.ExecutorService;
sangho0c2a3da2016-02-16 13:39:07 +090065import java.util.stream.Collectors;
66
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070067import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
sangho0c2a3da2016-02-16 13:39:07 +090068import static org.onlab.util.Tools.groupedThreads;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070069import static org.onosproject.openstacknetworking.Constants.*;
70import static org.onosproject.openstacknetworking.RulePopulatorUtil.buildExtension;
71import static org.onosproject.openstacknode.OpenstackNodeService.NodeType.COMPUTE;
72import static org.onosproject.openstacknode.OpenstackNodeService.NodeType.GATEWAY;
sangho0c2a3da2016-02-16 13:39:07 +090073
sangho0c2a3da2016-02-16 13:39:07 +090074@Component(immediate = true)
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090075@Service
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070076public class OpenstackRoutingManager extends AbstractVmHandler implements OpenstackRoutingService {
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090077
78 private final Logger log = LoggerFactory.getLogger(getClass());
sangho0c2a3da2016-02-16 13:39:07 +090079
80 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070081 protected FlowObjectiveService flowObjectiveService;
sangho0c2a3da2016-02-16 13:39:07 +090082
83 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
84 protected DeviceService deviceService;
85
86 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sangho93447f12016-02-24 00:33:22 +090087 protected OpenstackInterfaceService openstackService;
sangho0c2a3da2016-02-16 13:39:07 +090088
89 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070090 protected OpenstackNodeService nodeService;
sangho6032f342016-07-07 14:32:03 +090091
92 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +090093 protected ScalableGatewayService gatewayService;
Daniel Park23193902016-03-24 18:17:19 +090094
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070095 private final ExecutorService eventExecutor = newSingleThreadScheduledExecutor(
96 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
97 private final InternalNodeListener nodeListener = new InternalNodeListener();
sangho6032f342016-07-07 14:32:03 +090098
sangho0c2a3da2016-02-16 13:39:07 +090099 private ApplicationId appId;
sangho0c2a3da2016-02-16 13:39:07 +0900100
101 @Activate
102 protected void activate() {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700103 super.activate();
104 appId = coreService.registerApplication(ROUTING_APP_ID);
105 nodeService.addListener(nodeListener);
sangho0c2a3da2016-02-16 13:39:07 +0900106 }
107
108 @Deactivate
109 protected void deactivate() {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700110 nodeService.removeListener(nodeListener);
Kyuhwi Choi5e65e2c2016-04-01 11:48:15 +0900111 log.info("stopped");
sangho0c2a3da2016-02-16 13:39:07 +0900112 }
113
sangho0c2a3da2016-02-16 13:39:07 +0900114 @Override
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700115 public void createRouter(OpenstackRouter osRouter) {
sangho0c2a3da2016-02-16 13:39:07 +0900116 }
117
118 @Override
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700119 public void updateRouter(OpenstackRouter osRouter) {
120 if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
121 openstackService.ports().stream()
122 .filter(osPort -> osPort.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE) &&
123 osPort.deviceId().equals(osRouter.id()))
124 .forEach(osPort -> setExternalConnection(osRouter, osPort.networkId()));
125
126 log.info("Connected external gateway {} to router {}",
127 osRouter.gatewayExternalInfo().externalFixedIps(),
128 osRouter.name());
129 } else {
130 openstackService.ports().stream()
131 .filter(osPort -> osPort.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE) &&
132 osPort.deviceId().equals(osRouter.id()))
133 .forEach(osPort -> unsetExternalConnection(osRouter, osPort.networkId()));
134
135 log.info("Disconnected external gateway from router {}",
136 osRouter.name());
137 }
138 }
139
140 @Override
141 public void removeRouter(String osRouterId) {
142 // TODO implement this
143 }
144
145 @Override
146 public void addRouterInterface(OpenstackRouterInterface routerIface) {
147 OpenstackRouter osRouter = openstackRouter(routerIface.id());
148 OpenstackPort osPort = openstackService.port(routerIface.portId());
149 if (osRouter == null || osPort == null) {
150 log.warn("Failed to add router interface {}", routerIface);
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900151 return;
152 }
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700153
154 setRoutes(osRouter, Optional.empty());
155 if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
156 setExternalConnection(osRouter, osPort.networkId());
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900157 }
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700158 log.info("Connected {} to router {}", osPort.fixedIps(), osRouter.name());
sangho0c2a3da2016-02-16 13:39:07 +0900159 }
160
161 @Override
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700162 public void removeRouterInterface(OpenstackRouterInterface routerIface) {
163 OpenstackRouter osRouter = openstackService.router(routerIface.id());
164 if (osRouter == null) {
165 log.warn("Failed to remove router interface {}", routerIface);
Kyuhwi Choi5e65e2c2016-04-01 11:48:15 +0900166 return;
167 }
sanghod177f8f2016-06-29 21:52:23 +0900168
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700169 OpenstackSubnet osSubnet = openstackService.subnet(routerIface.subnetId());
170 OpenstackNetwork osNet = openstackService.network(osSubnet.networkId());
171
172 unsetRoutes(osRouter, osNet);
173 if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
174 unsetExternalConnection(osRouter, osNet.id());
Kyuhwi Choi5e65e2c2016-04-01 11:48:15 +0900175 }
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700176 log.info("Disconnected {} from router {}", osSubnet.cidr(), osRouter.name());
Kyuhwi Choi5e65e2c2016-04-01 11:48:15 +0900177 }
178
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700179 private void setExternalConnection(OpenstackRouter osRouter, String osNetId) {
180 if (!osRouter.gatewayExternalInfo().isEnablePnat()) {
181 log.debug("Source NAT is disabled");
sangho6032f342016-07-07 14:32:03 +0900182 return;
183 }
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700184
185 // FIXME router interface is subnet specific, not network
186 OpenstackNetwork osNet = openstackService.network(osNetId);
187 populateExternalRules(osNet);
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900188 }
189
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700190 private void unsetExternalConnection(OpenstackRouter osRouter, String osNetId) {
191 if (!osRouter.gatewayExternalInfo().isEnablePnat()) {
192 log.debug("Source NAT is disabled");
193 return;
sangho0c2a3da2016-02-16 13:39:07 +0900194 }
195
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700196 // FIXME router interface is subnet specific, not network
197 OpenstackNetwork osNet = openstackService.network(osNetId);
198 removeExternalRules(osNet);
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900199 }
200
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700201 private void setRoutes(OpenstackRouter osRouter, Optional<Host> host) {
202 Set<OpenstackNetwork> routableNets = routableNetworks(osRouter.id());
203 if (routableNets.size() < 2) {
204 // no other subnet interface is connected to this router, do nothing
205 return;
206 }
207
208 // FIXME router interface is subnet specific, not network
209 Set<String> routableNetIds = routableNets.stream()
210 .map(OpenstackNetwork::id)
211 .collect(Collectors.toSet());
212
213 Set<Host> hosts = host.isPresent() ? ImmutableSet.of(host.get()) :
214 Tools.stream(hostService.getHosts())
215 .filter(h -> routableNetIds.contains(h.annotations().value(NETWORK_ID)))
216 .collect(Collectors.toSet());
217
218 hosts.stream().forEach(h -> populateRoutingRules(h, routableNets));
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +0900219 }
220
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700221 private void unsetRoutes(OpenstackRouter osRouter, OpenstackNetwork osNet) {
222 // FIXME router interface is subnet specific, not network
223 Set<OpenstackNetwork> routableNets = routableNetworks(osRouter.id());
224 Tools.stream(hostService.getHosts())
225 .filter(h -> Objects.equals(
226 h.annotations().value(NETWORK_ID), osNet.id()))
227 .forEach(h -> removeRoutingRules(h, routableNets));
228
229 routableNets.stream().forEach(n -> {
230 Tools.stream(hostService.getHosts())
231 .filter(h -> Objects.equals(
232 h.annotations().value(NETWORK_ID),
233 n.id()))
234 .forEach(h -> removeRoutingRules(h, ImmutableSet.of(osNet)));
235 log.debug("Removed between {} to {}", n.name(), osNet.name());
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900236 });
sangho0c2a3da2016-02-16 13:39:07 +0900237 }
238
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700239 private OpenstackRouter openstackRouter(String routerId) {
sangho0c2a3da2016-02-16 13:39:07 +0900240 return openstackService.routers().stream().filter(r ->
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700241 r.id().equals(routerId)).iterator().next();
sangho0c2a3da2016-02-16 13:39:07 +0900242 }
243
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700244 private Optional<OpenstackPort> routerIfacePort(String osNetId) {
245 // FIXME router interface is subnet specific, not network
246 return openstackService.ports().stream()
247 .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE) &&
248 p.networkId().equals(osNetId))
sangho6032f342016-07-07 14:32:03 +0900249 .findAny();
250 }
251
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700252 private Set<OpenstackNetwork> routableNetworks(String osRouterId) {
253 // FIXME router interface is subnet specific, not network
254 return openstackService.ports().stream()
255 .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE) &&
256 p.deviceId().equals(osRouterId))
257 .map(p -> openstackService.network(p.networkId()))
258 .collect(Collectors.toSet());
259 }
sangho6032f342016-07-07 14:32:03 +0900260
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700261 private void populateExternalRules(OpenstackNetwork osNet) {
262 populateCnodeToGateway(Long.valueOf(osNet.segmentId()));
263 populateGatewayToController(Long.valueOf(osNet.segmentId()));
264 }
265
266 private void removeExternalRules(OpenstackNetwork osNet) {
267 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
268 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
269 .matchTunnelId(Long.valueOf(osNet.segmentId()))
270 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
271
272 nodeService.completeNodes().stream().forEach(node -> {
273 ForwardingObjective.Flag flag = node.type().equals(GATEWAY) ?
274 ForwardingObjective.Flag.VERSATILE :
275 ForwardingObjective.Flag.SPECIFIC;
276
277 RulePopulatorUtil.removeRule(
278 flowObjectiveService,
279 appId,
280 node.intBridge(),
281 sBuilder.build(),
282 flag,
283 ROUTING_RULE_PRIORITY);
284 });
285 }
286
287 private void populateRoutingRules(Host host, Set<OpenstackNetwork> osNets) {
288 String osNetId = host.annotations().value(NETWORK_ID);
289 if (osNetId == null) {
Daniel Park81a61a12016-02-26 08:24:44 +0900290 return;
291 }
292
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700293 DeviceId localDevice = host.location().deviceId();
294 PortNumber localPort = host.location().port();
295 if (!nodeService.dataIp(localDevice).isPresent()) {
296 log.warn("Failed to populate L3 rules");
297 return;
sangho6032f342016-07-07 14:32:03 +0900298 }
sanghod177f8f2016-06-29 21:52:23 +0900299
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700300 // TODO improve pipeline, do we have to install access rules between networks
301 // for every single VMs?
302 osNets.stream().filter(osNet -> !osNet.id().equals(osNetId)).forEach(osNet -> {
303 populateRoutingRulestoSameNode(
304 host.ipAddresses().stream().findFirst().get().getIp4Address(),
305 host.mac(),
306 localPort, localDevice,
307 Long.valueOf(osNet.segmentId()));
sanghod177f8f2016-06-29 21:52:23 +0900308
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700309 nodeService.completeNodes().stream()
310 .filter(node -> node.type().equals(COMPUTE))
311 .filter(node -> !node.intBridge().equals(localDevice))
312 .forEach(node -> populateRoutingRulestoDifferentNode(
313 host.ipAddresses().stream().findFirst().get().getIp4Address(),
314 Long.valueOf(osNet.segmentId()),
315 node.intBridge(),
316 nodeService.dataIp(localDevice).get().getIp4Address()));
317 });
Daniel Park81a61a12016-02-26 08:24:44 +0900318 }
319
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700320 private void removeRoutingRules(Host host, Set<OpenstackNetwork> osNets) {
321 String osNetId = host.annotations().value(NETWORK_ID);
322 if (osNetId == null) {
323 return;
sangho6032f342016-07-07 14:32:03 +0900324 }
325
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700326 osNets.stream().filter(osNet -> !osNet.id().equals(osNetId)).forEach(osNet -> {
327 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
328 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
329 .matchIPDst(host.ipAddresses().stream().findFirst().get().toIpPrefix())
330 .matchTunnelId(Long.valueOf(osNet.segmentId()));
sangho6032f342016-07-07 14:32:03 +0900331
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700332 nodeService.completeNodes().stream()
333 .filter(node -> node.type().equals(COMPUTE))
334 .forEach(node -> RulePopulatorUtil.removeRule(
335 flowObjectiveService,
336 appId,
337 node.intBridge(),
338 sBuilder.build(),
339 ForwardingObjective.Flag.SPECIFIC,
340 ROUTING_RULE_PRIORITY));
341 });
342 log.debug("Removed routing rule from {} to {}", host, osNets);
Daniel Park81a61a12016-02-26 08:24:44 +0900343 }
Kyuhwi Choi5e65e2c2016-04-01 11:48:15 +0900344
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700345 private void populateGatewayToController(long vni) {
346 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
347 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
sangho6032f342016-07-07 14:32:03 +0900348
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700349 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
350 .matchTunnelId(vni)
351 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
352 tBuilder.setOutput(PortNumber.CONTROLLER);
sangho6032f342016-07-07 14:32:03 +0900353
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700354 ForwardingObjective fo = DefaultForwardingObjective.builder()
355 .withSelector(sBuilder.build())
356 .withTreatment(tBuilder.build())
357 .withFlag(ForwardingObjective.Flag.VERSATILE)
358 .withPriority(ROUTING_RULE_PRIORITY)
359 .fromApp(appId)
360 .add();
sangho6032f342016-07-07 14:32:03 +0900361
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700362 gatewayService.getGatewayDeviceIds().stream()
363 .forEach(deviceId -> flowObjectiveService.forward(deviceId, fo));
364 }
sangho6032f342016-07-07 14:32:03 +0900365
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700366 private void populateCnodeToGateway(long vni) {
367 nodeService.completeNodes().stream()
368 .filter(node -> node.type().equals(COMPUTE))
369 .forEach(node -> populateRuleToGateway(
370 node.intBridge(),
371 gatewayService.getGatewayGroupId(node.intBridge()),
372 vni));
373 }
sangho6032f342016-07-07 14:32:03 +0900374
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700375 private void populateRuleToGateway(DeviceId deviceId, GroupId groupId, long vni) {
376 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
377 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
sangho6032f342016-07-07 14:32:03 +0900378
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700379 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
380 .matchTunnelId(vni)
381 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
382
383 tBuilder.group(groupId);
384 ForwardingObjective fo = DefaultForwardingObjective.builder()
385 .withSelector(sBuilder.build())
386 .withTreatment(tBuilder.build())
387 .withFlag(ForwardingObjective.Flag.SPECIFIC)
388 .withPriority(ROUTING_RULE_PRIORITY)
389 .fromApp(appId)
390 .add();
391
392 flowObjectiveService.forward(deviceId, fo);
393 }
394
395 private void populateRoutingRulestoDifferentNode(Ip4Address vmIp, long vni,
396 DeviceId deviceId, Ip4Address hostIp) {
397 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
398 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
399
400 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
401 .matchTunnelId(vni)
402 .matchIPDst(vmIp.toIpPrefix());
403 tBuilder.extension(buildExtension(deviceService, deviceId, hostIp), deviceId)
404 .setOutput(nodeService.tunnelPort(deviceId).get());
405
406 ForwardingObjective fo = DefaultForwardingObjective.builder()
407 .withSelector(sBuilder.build())
408 .withTreatment(tBuilder.build())
409 .withPriority(ROUTING_RULE_PRIORITY)
410 .withFlag(ForwardingObjective.Flag.SPECIFIC)
411 .fromApp(appId)
412 .add();
413
414 flowObjectiveService.forward(deviceId, fo);
415 }
416
417 private void populateRoutingRulestoSameNode(Ip4Address vmIp, MacAddress vmMac,
418 PortNumber port, DeviceId deviceId, long vni) {
419 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
420 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
421
422 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
423 .matchIPDst(vmIp.toIpPrefix())
424 .matchTunnelId(vni);
425
426 tBuilder.setEthDst(vmMac)
427 .setOutput(port);
428
429 ForwardingObjective fo = DefaultForwardingObjective.builder()
430 .withSelector(sBuilder.build())
431 .withTreatment(tBuilder.build())
432 .withPriority(ROUTING_RULE_PRIORITY)
433 .withFlag(ForwardingObjective.Flag.SPECIFIC)
434 .fromApp(appId)
435 .add();
436
437 flowObjectiveService.forward(deviceId, fo);
438 }
439
440 private void reloadRoutingRules() {
441 eventExecutor.execute(() -> openstackService.ports().stream()
442 .filter(osPort -> osPort.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE))
443 .forEach(osPort -> {
444 OpenstackRouter osRouter = openstackRouter(osPort.deviceId());
445 setRoutes(osRouter, Optional.empty());
446 if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
447 setExternalConnection(osRouter, osPort.networkId());
448 }
449 }));
450 }
451
452 @Override
453 protected void hostDetected(Host host) {
454 String osNetId = host.annotations().value(NETWORK_ID);
455 Optional<OpenstackPort> routerIface = routerIfacePort(osNetId);
456 if (!routerIface.isPresent()) {
457 return;
sangho6032f342016-07-07 14:32:03 +0900458 }
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700459 eventExecutor.execute(() -> setRoutes(
460 openstackRouter(routerIface.get().deviceId()),
461 Optional.of(host)));
462 }
463
464 @Override
465 protected void hostRemoved(Host host) {
466 String osNetId = host.annotations().value(NETWORK_ID);
467 Optional<OpenstackPort> routerIface = routerIfacePort(osNetId);
468 if (!routerIface.isPresent()) {
469 return;
470 }
471 Set<OpenstackNetwork> routableNets = routableNetworks(routerIface.get().deviceId());
472 eventExecutor.execute(() -> removeRoutingRules(host, routableNets));
473 }
474
475 private class InternalNodeListener implements OpenstackNodeListener {
Kyuhwi Choi5e65e2c2016-04-01 11:48:15 +0900476
477 @Override
sangho6032f342016-07-07 14:32:03 +0900478 public void event(OpenstackNodeEvent event) {
479 OpenstackNode node = event.node();
480
481 switch (event.type()) {
482 case COMPLETE:
483 log.info("COMPLETE node {} detected", node.hostname());
Hyunsun Moon5aa480b2016-08-03 12:23:14 -0700484 eventExecutor.execute(() -> {
485 if (node.type() == GATEWAY) {
486 GatewayNode gnode = GatewayNode.builder()
487 .gatewayDeviceId(node.intBridge())
488 .dataIpAddress(node.dataIp().getIp4Address())
489 .uplinkIntf(node.externalPortName().get())
490 .build();
491 gatewayService.addGatewayNode(gnode);
492 }
493 reloadRoutingRules();
494 });
sangho6032f342016-07-07 14:32:03 +0900495 break;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700496 case INIT:
497 case DEVICE_CREATED:
sangho6032f342016-07-07 14:32:03 +0900498 case INCOMPLETE:
sangho6032f342016-07-07 14:32:03 +0900499 default:
500 break;
Kyuhwi Choi5e65e2c2016-04-01 11:48:15 +0900501 }
sangho6032f342016-07-07 14:32:03 +0900502 }
503 }
sangho0c2a3da2016-02-16 13:39:07 +0900504}