blob: f7989bd36164493d4e7bcd6e98d82c4abe522088 [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
sangho0c2a3da2016-02-16 13:39:07 +090018import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20import org.apache.felix.scr.annotations.Deactivate;
21import org.apache.felix.scr.annotations.Reference;
22import org.apache.felix.scr.annotations.ReferenceCardinality;
23import org.apache.felix.scr.annotations.Service;
24import org.onlab.packet.Ethernet;
Daniel Parka8d896c2016-08-26 14:31:33 +090025import org.onlab.packet.IPv4;
sangho0c2a3da2016-02-16 13:39:07 +090026import org.onlab.packet.Ip4Address;
sanghofb3b5012016-11-10 15:47:53 +090027import org.onlab.packet.IpAddress;
sangho3d2bf9c2016-08-26 17:19:55 +090028import org.onlab.packet.IpPrefix;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070029import org.onlab.util.Tools;
sangho0c2a3da2016-02-16 13:39:07 +090030import org.onosproject.core.ApplicationId;
sanghofb3b5012016-11-10 15:47:53 +090031import org.onosproject.core.CoreService;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070032import org.onosproject.core.GroupId;
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090033import org.onosproject.net.DeviceId;
sangho6032f342016-07-07 14:32:03 +090034import org.onosproject.net.Host;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070035import org.onosproject.net.PortNumber;
sangho0c2a3da2016-02-16 13:39:07 +090036import org.onosproject.net.device.DeviceService;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070037import org.onosproject.net.flow.DefaultTrafficSelector;
38import org.onosproject.net.flow.DefaultTrafficTreatment;
39import org.onosproject.net.flow.TrafficSelector;
40import org.onosproject.net.flow.TrafficTreatment;
sangho0c2a3da2016-02-16 13:39:07 +090041import org.onosproject.net.flowobjective.FlowObjectiveService;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070042import org.onosproject.net.flowobjective.ForwardingObjective;
sangho93447f12016-02-24 00:33:22 +090043import org.onosproject.openstackinterface.OpenstackInterfaceService;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070044import org.onosproject.openstackinterface.OpenstackNetwork;
sangho93447f12016-02-24 00:33:22 +090045import 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
sangho3d2bf9c2016-08-26 17:19:55 +090061import java.util.HashMap;
62import java.util.Map;
Daniel Park23193902016-03-24 18:17:19 +090063import java.util.Optional;
sangho6032f342016-07-07 14:32:03 +090064import java.util.Set;
sangho0c2a3da2016-02-16 13:39:07 +090065import java.util.concurrent.ExecutorService;
sangho0c2a3da2016-02-16 13:39:07 +090066import java.util.stream.Collectors;
67
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070068import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
sangho0c2a3da2016-02-16 13:39:07 +090069import static org.onlab.util.Tools.groupedThreads;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070070import static org.onosproject.openstacknetworking.Constants.*;
71import static org.onosproject.openstacknetworking.RulePopulatorUtil.buildExtension;
72import static org.onosproject.openstacknode.OpenstackNodeService.NodeType.COMPUTE;
73import static org.onosproject.openstacknode.OpenstackNodeService.NodeType.GATEWAY;
sangho0c2a3da2016-02-16 13:39:07 +090074
sangho0c2a3da2016-02-16 13:39:07 +090075@Component(immediate = true)
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090076@Service
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070077public class OpenstackRoutingManager extends AbstractVmHandler implements OpenstackRoutingService {
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090078
79 private final Logger log = LoggerFactory.getLogger(getClass());
sangho0c2a3da2016-02-16 13:39:07 +090080
81 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070082 protected FlowObjectiveService flowObjectiveService;
sangho0c2a3da2016-02-16 13:39:07 +090083
84 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sangho93447f12016-02-24 00:33:22 +090085 protected OpenstackInterfaceService openstackService;
sangho0c2a3da2016-02-16 13:39:07 +090086
87 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070088 protected OpenstackNodeService nodeService;
sangho6032f342016-07-07 14:32:03 +090089
90 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +090091 protected ScalableGatewayService gatewayService;
Daniel Park23193902016-03-24 18:17:19 +090092
sanghofb3b5012016-11-10 15:47:53 +090093 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
94 protected CoreService coreService;
95
96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
97 protected DeviceService deviceService;
98
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070099 private final ExecutorService eventExecutor = newSingleThreadScheduledExecutor(
100 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
101 private final InternalNodeListener nodeListener = new InternalNodeListener();
sangho6032f342016-07-07 14:32:03 +0900102
sangho0c2a3da2016-02-16 13:39:07 +0900103 private ApplicationId appId;
sangho0c2a3da2016-02-16 13:39:07 +0900104
105 @Activate
106 protected void activate() {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700107 super.activate();
108 appId = coreService.registerApplication(ROUTING_APP_ID);
109 nodeService.addListener(nodeListener);
sangho0c2a3da2016-02-16 13:39:07 +0900110 }
111
112 @Deactivate
113 protected void deactivate() {
sanghofb3b5012016-11-10 15:47:53 +0900114 super.deactivate();
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700115 nodeService.removeListener(nodeListener);
Kyuhwi Choi5e65e2c2016-04-01 11:48:15 +0900116 log.info("stopped");
sangho0c2a3da2016-02-16 13:39:07 +0900117 }
118
sangho0c2a3da2016-02-16 13:39:07 +0900119 @Override
sanghofb3b5012016-11-10 15:47:53 +0900120 protected void hostDetected(Host host) {
121 // Installs forwarding flow rules to VMs in different nodes and different subnets
122 // that are connected via a router
123 Optional<OpenstackRouter> routerOfTheHost = getRouter(host);
124
125 if (!routerOfTheHost.isPresent()) {
126 return;
127 }
128
129 routableSubNets(routerOfTheHost.get().id()).stream()
130 .filter(subnet -> !subnet.id().equals(host.annotations().value(SUBNET_ID)))
131 .forEach(subnet -> setForwardingRulesAmongHostsInDifferentCnodes(host, getHosts(subnet), true));
132 }
133
134 @Override
135 protected void hostRemoved(Host host) {
136 // Removes forwarding flow rules to VMs in different nodes and different subnets
137 // that are connected via a router
138 Optional<OpenstackRouter> routerOfTheHost = getRouter(host);
139 if (!routerOfTheHost.isPresent()) {
140 return;
141 }
142
143 routableSubNets(routerOfTheHost.get().id()).stream()
144 .filter(subnet -> !subnet.id().equals(host.annotations().value(SUBNET_ID)))
145 .forEach(subnet -> setForwardingRulesAmongHostsInDifferentCnodes(host, getHosts(subnet), false));
146 }
147
148 @Override
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700149 public void createRouter(OpenstackRouter osRouter) {
sangho0c2a3da2016-02-16 13:39:07 +0900150 }
151
152 @Override
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700153 public void updateRouter(OpenstackRouter osRouter) {
154 if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
sanghofb3b5012016-11-10 15:47:53 +0900155 routableSubNets(osRouter.id()).stream()
156 .forEach(subnet -> setExternalConnection(osRouter, subnet, true));
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700157
158 log.info("Connected external gateway {} to router {}",
159 osRouter.gatewayExternalInfo().externalFixedIps(),
160 osRouter.name());
161 } else {
sanghofb3b5012016-11-10 15:47:53 +0900162 routableSubNets(osRouter.id()).stream()
163 .forEach(subnet -> setExternalConnection(osRouter, subnet, false));
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700164
165 log.info("Disconnected external gateway from router {}",
166 osRouter.name());
167 }
168 }
169
170 @Override
171 public void removeRouter(String osRouterId) {
sanghofb3b5012016-11-10 15:47:53 +0900172 // Nothing to do
173 // All interfaces need to be removed before the router is removed,
174 // and all related flow rues are removed when the interfaces are removed.
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700175 }
176
177 @Override
sanghofb3b5012016-11-10 15:47:53 +0900178 public void addRouterInterface(OpenstackRouterInterface routerIfaceAdded) {
179 OpenstackRouter osRouter = openstackRouter(routerIfaceAdded.id());
180 OpenstackSubnet osSubnetAdded = openstackService.subnet(routerIfaceAdded.subnetId());
181 if (osRouter == null || osSubnetAdded == null) {
182 log.warn("Failed to add router interface {}", routerIfaceAdded);
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900183 return;
184 }
sanghofb3b5012016-11-10 15:47:53 +0900185 handleRouterInterfaces(osRouter, osSubnetAdded);
sangho0c2a3da2016-02-16 13:39:07 +0900186 }
187
188 @Override
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700189 public void removeRouterInterface(OpenstackRouterInterface routerIface) {
190 OpenstackRouter osRouter = openstackService.router(routerIface.id());
sanghofb3b5012016-11-10 15:47:53 +0900191 OpenstackSubnet osSubnetRemoved = openstackService.subnet(routerIface.subnetId());
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700192 if (osRouter == null) {
193 log.warn("Failed to remove router interface {}", routerIface);
Kyuhwi Choi5e65e2c2016-04-01 11:48:15 +0900194 return;
195 }
sanghofb3b5012016-11-10 15:47:53 +0900196 handleRouterInterfacesRemoved(osRouter, osSubnetRemoved);
sanghod177f8f2016-06-29 21:52:23 +0900197
sanghofb3b5012016-11-10 15:47:53 +0900198 log.info("Disconnected {} from router {}", osSubnetRemoved.cidr(), osRouter.name());
199 }
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700200
sanghofb3b5012016-11-10 15:47:53 +0900201 private void handleRouterInterfaces(OpenstackRouter osRouter, OpenstackSubnet osSubnetAdded) {
202 OpenstackNetwork osNetworkAdded = openstackService.network(osSubnetAdded.networkId());
203 if (osNetworkAdded == null) { // in case of external network subnet
204 return;
205 }
Daniel Parka8d896c2016-08-26 14:31:33 +0900206
sanghofb3b5012016-11-10 15:47:53 +0900207 // Sets flow rules for routing among subnets connected to a router.
208 setRoutesAmongSubnets(osRouter, osSubnetAdded, true);
Daniel Parka8d896c2016-08-26 14:31:33 +0900209
sanghofb3b5012016-11-10 15:47:53 +0900210 // Sets flow rules for forwarding "packets going to external networks" to gateway nodes.
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700211 if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
sanghofb3b5012016-11-10 15:47:53 +0900212 setExternalConnection(osRouter, osSubnetAdded, true);
sangho6032f342016-07-07 14:32:03 +0900213 }
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700214
sanghofb3b5012016-11-10 15:47:53 +0900215 // Sets flow rules to handle ping to the virtual gateway.
216 Ip4Address vGatewayIp = Ip4Address.valueOf(osSubnetAdded.gatewayIp());
217 gatewayService.getGatewayDeviceIds()
218 .forEach(deviceId -> setGatewayIcmpRule(vGatewayIp, deviceId, true));
219
220 // Sets east-west routing rules for VMs in different Cnode to Switching Table.
221 setForwardingRulesForEastWestRouting(osRouter, osSubnetAdded, true);
222
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900223 }
224
sanghofb3b5012016-11-10 15:47:53 +0900225 private void handleRouterInterfacesRemoved(OpenstackRouter osRouter, OpenstackSubnet osSubnetRemoved) {
226
227 // Removes flow rules for routing among subnets connected to a router.
228 setRoutesAmongSubnets(osRouter, osSubnetRemoved, false);
229
230 // Removes flow rules for forwarding "packets going to external networks" to gateway nodes.
231 if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
232 setExternalConnection(osRouter, osSubnetRemoved, false);
sangho0c2a3da2016-02-16 13:39:07 +0900233 }
234
sanghofb3b5012016-11-10 15:47:53 +0900235 // Removes flow rules to handle ping to the virtual gateway.
236 Ip4Address vGatewayIp = Ip4Address.valueOf(osSubnetRemoved.gatewayIp());
237 gatewayService.getGatewayDeviceIds()
238 .forEach(deviceId -> setGatewayIcmpRule(vGatewayIp, deviceId, false));
239
240 // Removes east-west routing rules for VMs in different Cnode to Switching Table.
241 setForwardingRulesForEastWestRouting(osRouter, osSubnetRemoved, false);
242
243 // Resets east-west routing rules for VMs in different Cnode to Switching Table.
244 routableSubNets(osRouter.id()).stream()
245 .forEach(subnet -> setForwardingRulesForEastWestRouting(osRouter, subnet, true));
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900246 }
247
sanghofb3b5012016-11-10 15:47:53 +0900248 private void setRoutesAmongSubnets(OpenstackRouter osRouter, OpenstackSubnet osSubnetAdded, boolean install) {
sangho3d2bf9c2016-08-26 17:19:55 +0900249 Set<OpenstackSubnet> routableSubNets = routableSubNets(osRouter.id());
250 if (routableSubNets.size() < 2) {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700251 // no other subnet interface is connected to this router, do nothing
252 return;
253 }
254
sangho3d2bf9c2016-08-26 17:19:55 +0900255 Map<String, String> vniMap = new HashMap<>();
Sho SHIMIZU8ebb04a2016-10-06 15:58:29 -0700256 openstackService.networks().forEach(n -> vniMap.put(n.id(), n.segmentId()));
sangho3d2bf9c2016-08-26 17:19:55 +0900257
sanghofb3b5012016-11-10 15:47:53 +0900258 routableSubNets.stream()
259 .filter(subnet -> !subnet.id().equals(osSubnetAdded.id()))
260 .filter(subnet -> vniMap.get(subnet.networkId()) != null)
261 .forEach(subnet -> nodeService.completeNodes().stream()
262 .filter(node -> node.type().equals(COMPUTE))
263 .forEach(node -> {
264 setRoutingRules(node.intBridge(),
265 Integer.parseInt(vniMap.get(subnet.networkId())),
266 Integer.parseInt(vniMap.get(osSubnetAdded.networkId())),
267 subnet, osSubnetAdded, install);
268 setRoutingRules(node.intBridge(),
269 Integer.parseInt(vniMap.get(osSubnetAdded.networkId())),
270 Integer.parseInt(vniMap.get(subnet.networkId())),
271 osSubnetAdded, subnet, install);
272 }
273 ));
Daniel Park81a61a12016-02-26 08:24:44 +0900274 }
275
sanghofb3b5012016-11-10 15:47:53 +0900276 private void setRoutingRules(DeviceId deviceId, int srcVni, int dstVni,
277 OpenstackSubnet subnetSrc, OpenstackSubnet subnetDst, boolean install) {
sangho6032f342016-07-07 14:32:03 +0900278
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700279 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
280 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
sangho6032f342016-07-07 14:32:03 +0900281
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700282 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
sanghofb3b5012016-11-10 15:47:53 +0900283 .matchTunnelId(srcVni)
284 .matchIPSrc(IpPrefix.valueOf(subnetSrc.cidr()))
285 .matchIPDst(IpPrefix.valueOf(subnetDst.cidr()));
sangho6032f342016-07-07 14:32:03 +0900286
sanghofb3b5012016-11-10 15:47:53 +0900287 tBuilder.setTunnelId(dstVni);
sangho6032f342016-07-07 14:32:03 +0900288
sanghofb3b5012016-11-10 15:47:53 +0900289 RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
290 tBuilder.build(), ForwardingObjective.Flag.SPECIFIC, EW_ROUTING_RULE_PRIORITY, install);
291
292 // Flow rules for destination is in different subnet and different node,
293 // because VNI is converted to destination VNI in the source VM node.
294 sBuilder = DefaultTrafficSelector.builder();
295 tBuilder = DefaultTrafficTreatment.builder();
296
297 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
298 .matchTunnelId(dstVni)
299 .matchIPSrc(IpPrefix.valueOf(subnetSrc.cidr()))
300 .matchIPDst(IpPrefix.valueOf(subnetDst.cidr()));
301
302 tBuilder.setTunnelId(dstVni);
303
304 RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
305 tBuilder.build(), ForwardingObjective.Flag.SPECIFIC, EW_ROUTING_RULE_PRIORITY, install);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700306 }
sangho6032f342016-07-07 14:32:03 +0900307
sanghofb3b5012016-11-10 15:47:53 +0900308 private void setExternalConnection(OpenstackRouter osRouter, OpenstackSubnet osSubNet, boolean install) {
309 if (!osRouter.gatewayExternalInfo().isEnablePnat()) {
310 log.debug("Source NAT is disabled");
311 return;
312 }
313
314 //OpenstackSubnet osSubNet = openstackService.subnet(osSubNetId);
315 OpenstackNetwork osNet = openstackService.network(osSubNet.networkId());
316
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700317 nodeService.completeNodes().stream()
318 .filter(node -> node.type().equals(COMPUTE))
sanghofb3b5012016-11-10 15:47:53 +0900319 .forEach(node -> setRulesToGateway(
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700320 node.intBridge(),
321 gatewayService.getGatewayGroupId(node.intBridge()),
sanghofb3b5012016-11-10 15:47:53 +0900322 Long.valueOf(osNet.segmentId()), osSubNet.cidr(), install));
323
324 // Is this for PNAT ??
325 setRulesForGatewayToController(Long.valueOf(osNet.segmentId()), osSubNet.cidr(), install);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700326 }
sangho6032f342016-07-07 14:32:03 +0900327
sanghofb3b5012016-11-10 15:47:53 +0900328 private void setRulesToGateway(DeviceId deviceId, GroupId groupId, long vni, String cidr, boolean install) {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700329 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
330 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
sangho6032f342016-07-07 14:32:03 +0900331
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700332 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
333 .matchTunnelId(vni)
sangho3d2bf9c2016-08-26 17:19:55 +0900334 .matchIPSrc(IpPrefix.valueOf(cidr))
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700335 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
336
337 tBuilder.group(groupId);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700338
sanghofb3b5012016-11-10 15:47:53 +0900339 RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
340 tBuilder.build(), ForwardingObjective.Flag.SPECIFIC, ROUTING_RULE_PRIORITY, install);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700341 }
342
sanghofb3b5012016-11-10 15:47:53 +0900343 private void setRulesForGatewayToController(long vni, String subNetCidr, boolean install) {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700344 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
345 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
346
347 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
348 .matchTunnelId(vni)
sanghofb3b5012016-11-10 15:47:53 +0900349 .matchIPSrc(IpPrefix.valueOf(subNetCidr))
350 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
351 tBuilder.setOutput(PortNumber.CONTROLLER);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700352
sanghofb3b5012016-11-10 15:47:53 +0900353 gatewayService.getGatewayDeviceIds().forEach(deviceId ->
354 RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
355 tBuilder.build(), ForwardingObjective.Flag.VERSATILE, ROUTING_RULE_PRIORITY, install));
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700356 }
357
sanghofb3b5012016-11-10 15:47:53 +0900358 private void setGatewayIcmpRule(Ip4Address gatewayIp, DeviceId deviceId, boolean install) {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700359 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
360 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
361
362 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
sanghofb3b5012016-11-10 15:47:53 +0900363 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
364 .matchIPDst(gatewayIp.toIpPrefix());
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700365
sanghofb3b5012016-11-10 15:47:53 +0900366 tBuilder.setOutput(PortNumber.CONTROLLER);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700367
sanghofb3b5012016-11-10 15:47:53 +0900368 RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
369 tBuilder.build(), ForwardingObjective.Flag.VERSATILE, GATEWAY_ICMP_PRIORITY, install);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700370 }
371
sanghofb3b5012016-11-10 15:47:53 +0900372 private void setForwardingRulesForEastWestRouting(OpenstackRouter router, OpenstackSubnet subnetAdded,
373 boolean install) {
Daniel Parka8d896c2016-08-26 14:31:33 +0900374
sanghofb3b5012016-11-10 15:47:53 +0900375 Set<OpenstackSubnet> subnets = routableSubNets(router.id());
Daniel Parka8d896c2016-08-26 14:31:33 +0900376
sanghofb3b5012016-11-10 15:47:53 +0900377 Set<Host> hosts = Tools.stream(hostService.getHosts())
378 .filter(h -> getVni(h).equals(openstackService.network(subnetAdded.networkId()).segmentId()))
379 .collect(Collectors.toSet());
380
381 subnets.stream()
382 .filter(subnet -> !subnet.id().equals(subnetAdded.id()))
383 .forEach(subnet -> getHosts(subnet)
384 .forEach(h -> setForwardingRulesAmongHostsInDifferentCnodes(h, hosts, install)));
385 }
386
387 private void setForwardingRulesAmongHostsInDifferentCnodes(Host host, Set<Host> remoteHosts, boolean install) {
388 Ip4Address localVmIp = getIp(host);
389 DeviceId localDeviceId = host.location().deviceId();
390 Optional<IpAddress> localDataIp = nodeService.dataIp(localDeviceId);
391
392 if (!localDataIp.isPresent()) {
393 log.debug("Failed to get data IP for device {}",
394 host.location().deviceId());
395 return;
396 }
397
398 remoteHosts.stream()
399 .filter(remoteHost -> !host.location().deviceId().equals(remoteHost.location().deviceId()))
400 .forEach(remoteVm -> {
401 Optional<IpAddress> remoteDataIp = nodeService.dataIp(remoteVm.location().deviceId());
402 if (remoteDataIp.isPresent()) {
403 setVxLanFlowRule(getVni(remoteVm),
404 localDeviceId,
405 remoteDataIp.get().getIp4Address(),
406 getIp(remoteVm), install);
407
408 setVxLanFlowRule(getVni(host),
409 remoteVm.location().deviceId(),
410 localDataIp.get().getIp4Address(),
411 localVmIp, install);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700412 }
sanghofb3b5012016-11-10 15:47:53 +0900413 });
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700414 }
415
sanghofb3b5012016-11-10 15:47:53 +0900416 private void setVxLanFlowRule(String vni, DeviceId deviceId, Ip4Address remoteIp,
417 Ip4Address vmIp, boolean install) {
418 Optional<PortNumber> tunnelPort = nodeService.tunnelPort(deviceId);
419 if (!tunnelPort.isPresent()) {
420 log.warn("Failed to get tunnel port from {}", deviceId);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700421 return;
sangho6032f342016-07-07 14:32:03 +0900422 }
sanghofb3b5012016-11-10 15:47:53 +0900423
424 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
425 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
426
427 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
428 .matchTunnelId(Long.parseLong(vni))
429 .matchIPDst(vmIp.toIpPrefix());
430 tBuilder.extension(buildExtension(deviceService, deviceId, remoteIp), deviceId)
431 .setOutput(tunnelPort.get());
432
433 RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
434 tBuilder.build(), ForwardingObjective.Flag.SPECIFIC, SWITCHING_RULE_PRIORITY, install);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700435 }
436
sanghofb3b5012016-11-10 15:47:53 +0900437
438 private OpenstackRouter openstackRouter(String routerId) {
439 return openstackService.routers().stream().filter(r ->
440 r.id().equals(routerId)).iterator().next();
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700441 }
442
jskimaa851932016-10-27 17:45:30 +0900443 @Override
444 public void reinstallVmFlow(Host host) {
sanghofb3b5012016-11-10 15:47:53 +0900445 // TODO: implements later
jskimaa851932016-10-27 17:45:30 +0900446 }
447
448 @Override
449 public void purgeVmFlow(Host host) {
sanghofb3b5012016-11-10 15:47:53 +0900450 // TODO: implements later
jskimaa851932016-10-27 17:45:30 +0900451 }
452
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700453 private class InternalNodeListener implements OpenstackNodeListener {
Kyuhwi Choi5e65e2c2016-04-01 11:48:15 +0900454
455 @Override
sangho6032f342016-07-07 14:32:03 +0900456 public void event(OpenstackNodeEvent event) {
457 OpenstackNode node = event.node();
458
459 switch (event.type()) {
460 case COMPLETE:
sanghofb3b5012016-11-10 15:47:53 +0900461 case INCOMPLETE:
sangho6032f342016-07-07 14:32:03 +0900462 log.info("COMPLETE node {} detected", node.hostname());
Hyunsun Moon5aa480b2016-08-03 12:23:14 -0700463 eventExecutor.execute(() -> {
464 if (node.type() == GATEWAY) {
465 GatewayNode gnode = GatewayNode.builder()
466 .gatewayDeviceId(node.intBridge())
467 .dataIpAddress(node.dataIp().getIp4Address())
468 .uplinkIntf(node.externalPortName().get())
469 .build();
470 gatewayService.addGatewayNode(gnode);
471 }
Hyunsun Moon5aa480b2016-08-03 12:23:14 -0700472 });
sanghofb3b5012016-11-10 15:47:53 +0900473 openstackService.routers().stream()
474 .forEach(router -> routableSubNets(router.id()).stream()
475 .forEach(subnet -> handleRouterInterfaces(router, subnet)));
sangho6032f342016-07-07 14:32:03 +0900476 break;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700477 case INIT:
478 case DEVICE_CREATED:
sangho6032f342016-07-07 14:32:03 +0900479 default:
480 break;
Kyuhwi Choi5e65e2c2016-04-01 11:48:15 +0900481 }
sangho6032f342016-07-07 14:32:03 +0900482 }
483 }
sangho0c2a3da2016-02-16 13:39:07 +0900484}