blob: 248233325458c0f6187c0c213575a73301b87ca9 [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 */
Hyunsun Moon05400872017-02-07 17:11:25 +090016package org.onosproject.openstacknetworking.impl;
sangho0c2a3da2016-02-16 13:39:07 +090017
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;
Hyunsun Moon05400872017-02-07 17:11:25 +090048import org.onosproject.openstacknetworking.api.Constants;
49import org.onosproject.openstacknetworking.api.OpenstackRoutingService;
sangho6032f342016-07-07 14:32:03 +090050import org.onosproject.openstacknode.OpenstackNode;
51import org.onosproject.openstacknode.OpenstackNodeEvent;
52import org.onosproject.openstacknode.OpenstackNodeListener;
53import org.onosproject.openstacknode.OpenstackNodeService;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070054import org.onosproject.scalablegateway.api.GatewayNode;
55import org.onosproject.scalablegateway.api.ScalableGatewayService;
sangho0c2a3da2016-02-16 13:39:07 +090056import org.slf4j.Logger;
57import org.slf4j.LoggerFactory;
58
sangho3d2bf9c2016-08-26 17:19:55 +090059import java.util.HashMap;
60import java.util.Map;
Daniel Park23193902016-03-24 18:17:19 +090061import java.util.Optional;
sangho6032f342016-07-07 14:32:03 +090062import java.util.Set;
sangho0c2a3da2016-02-16 13:39:07 +090063import java.util.concurrent.ExecutorService;
sangho0c2a3da2016-02-16 13:39:07 +090064import java.util.stream.Collectors;
65
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070066import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
sangho0c2a3da2016-02-16 13:39:07 +090067import static org.onlab.util.Tools.groupedThreads;
Hyunsun Moon05400872017-02-07 17:11:25 +090068import static org.onosproject.openstacknetworking.api.Constants.*;
69import static org.onosproject.openstacknetworking.impl.RulePopulatorUtil.buildExtension;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070070import static org.onosproject.openstacknode.OpenstackNodeService.NodeType.COMPUTE;
71import static org.onosproject.openstacknode.OpenstackNodeService.NodeType.GATEWAY;
sangho0c2a3da2016-02-16 13:39:07 +090072
sangho0c2a3da2016-02-16 13:39:07 +090073@Component(immediate = true)
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090074@Service
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070075public class OpenstackRoutingManager extends AbstractVmHandler implements OpenstackRoutingService {
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090076
77 private final Logger log = LoggerFactory.getLogger(getClass());
sangho0c2a3da2016-02-16 13:39:07 +090078
79 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070080 protected FlowObjectiveService flowObjectiveService;
sangho0c2a3da2016-02-16 13:39:07 +090081
82 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
sangho93447f12016-02-24 00:33:22 +090083 protected OpenstackInterfaceService openstackService;
sangho0c2a3da2016-02-16 13:39:07 +090084
85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070086 protected OpenstackNodeService nodeService;
sangho6032f342016-07-07 14:32:03 +090087
88 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Kyuhwi Choi92d9ea42016-06-13 17:28:00 +090089 protected ScalableGatewayService gatewayService;
Daniel Park23193902016-03-24 18:17:19 +090090
sanghofb3b5012016-11-10 15:47:53 +090091 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
92 protected CoreService coreService;
93
94 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
95 protected DeviceService deviceService;
96
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070097 private final ExecutorService eventExecutor = newSingleThreadScheduledExecutor(
98 groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
99 private final InternalNodeListener nodeListener = new InternalNodeListener();
sangho6032f342016-07-07 14:32:03 +0900100
sangho0c2a3da2016-02-16 13:39:07 +0900101 private ApplicationId appId;
sangho0c2a3da2016-02-16 13:39:07 +0900102
103 @Activate
104 protected void activate() {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700105 super.activate();
106 appId = coreService.registerApplication(ROUTING_APP_ID);
107 nodeService.addListener(nodeListener);
sangho0c2a3da2016-02-16 13:39:07 +0900108 }
109
110 @Deactivate
111 protected void deactivate() {
sanghofb3b5012016-11-10 15:47:53 +0900112 super.deactivate();
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700113 nodeService.removeListener(nodeListener);
Kyuhwi Choi5e65e2c2016-04-01 11:48:15 +0900114 log.info("stopped");
sangho0c2a3da2016-02-16 13:39:07 +0900115 }
116
sangho0c2a3da2016-02-16 13:39:07 +0900117 @Override
sanghofb3b5012016-11-10 15:47:53 +0900118 protected void hostDetected(Host host) {
119 // Installs forwarding flow rules to VMs in different nodes and different subnets
120 // that are connected via a router
121 Optional<OpenstackRouter> routerOfTheHost = getRouter(host);
122
123 if (!routerOfTheHost.isPresent()) {
124 return;
125 }
126
127 routableSubNets(routerOfTheHost.get().id()).stream()
128 .filter(subnet -> !subnet.id().equals(host.annotations().value(SUBNET_ID)))
129 .forEach(subnet -> setForwardingRulesAmongHostsInDifferentCnodes(host, getHosts(subnet), true));
130 }
131
132 @Override
133 protected void hostRemoved(Host host) {
134 // Removes forwarding flow rules to VMs in different nodes and different subnets
135 // that are connected via a router
136 Optional<OpenstackRouter> routerOfTheHost = getRouter(host);
137 if (!routerOfTheHost.isPresent()) {
138 return;
139 }
140
141 routableSubNets(routerOfTheHost.get().id()).stream()
142 .filter(subnet -> !subnet.id().equals(host.annotations().value(SUBNET_ID)))
143 .forEach(subnet -> setForwardingRulesAmongHostsInDifferentCnodes(host, getHosts(subnet), false));
144 }
145
146 @Override
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700147 public void createRouter(OpenstackRouter osRouter) {
sangho0c2a3da2016-02-16 13:39:07 +0900148 }
149
150 @Override
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700151 public void updateRouter(OpenstackRouter osRouter) {
152 if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
sanghofb3b5012016-11-10 15:47:53 +0900153 routableSubNets(osRouter.id()).stream()
154 .forEach(subnet -> setExternalConnection(osRouter, subnet, true));
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700155
156 log.info("Connected external gateway {} to router {}",
157 osRouter.gatewayExternalInfo().externalFixedIps(),
158 osRouter.name());
159 } else {
sanghofb3b5012016-11-10 15:47:53 +0900160 routableSubNets(osRouter.id()).stream()
161 .forEach(subnet -> setExternalConnection(osRouter, subnet, false));
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700162
163 log.info("Disconnected external gateway from router {}",
164 osRouter.name());
165 }
166 }
167
168 @Override
169 public void removeRouter(String osRouterId) {
sanghofb3b5012016-11-10 15:47:53 +0900170 // Nothing to do
171 // All interfaces need to be removed before the router is removed,
172 // and all related flow rues are removed when the interfaces are removed.
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700173 }
174
175 @Override
sanghofb3b5012016-11-10 15:47:53 +0900176 public void addRouterInterface(OpenstackRouterInterface routerIfaceAdded) {
177 OpenstackRouter osRouter = openstackRouter(routerIfaceAdded.id());
178 OpenstackSubnet osSubnetAdded = openstackService.subnet(routerIfaceAdded.subnetId());
179 if (osRouter == null || osSubnetAdded == null) {
180 log.warn("Failed to add router interface {}", routerIfaceAdded);
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900181 return;
182 }
sanghofb3b5012016-11-10 15:47:53 +0900183 handleRouterInterfaces(osRouter, osSubnetAdded);
sangho0c2a3da2016-02-16 13:39:07 +0900184 }
185
186 @Override
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700187 public void removeRouterInterface(OpenstackRouterInterface routerIface) {
188 OpenstackRouter osRouter = openstackService.router(routerIface.id());
sanghofb3b5012016-11-10 15:47:53 +0900189 OpenstackSubnet osSubnetRemoved = openstackService.subnet(routerIface.subnetId());
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700190 if (osRouter == null) {
191 log.warn("Failed to remove router interface {}", routerIface);
Kyuhwi Choi5e65e2c2016-04-01 11:48:15 +0900192 return;
193 }
sanghofb3b5012016-11-10 15:47:53 +0900194 handleRouterInterfacesRemoved(osRouter, osSubnetRemoved);
sanghod177f8f2016-06-29 21:52:23 +0900195
sanghofb3b5012016-11-10 15:47:53 +0900196 log.info("Disconnected {} from router {}", osSubnetRemoved.cidr(), osRouter.name());
197 }
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700198
sanghofb3b5012016-11-10 15:47:53 +0900199 private void handleRouterInterfaces(OpenstackRouter osRouter, OpenstackSubnet osSubnetAdded) {
200 OpenstackNetwork osNetworkAdded = openstackService.network(osSubnetAdded.networkId());
201 if (osNetworkAdded == null) { // in case of external network subnet
202 return;
203 }
Daniel Parka8d896c2016-08-26 14:31:33 +0900204
sanghofb3b5012016-11-10 15:47:53 +0900205 // Sets flow rules for routing among subnets connected to a router.
206 setRoutesAmongSubnets(osRouter, osSubnetAdded, true);
Daniel Parka8d896c2016-08-26 14:31:33 +0900207
sanghofb3b5012016-11-10 15:47:53 +0900208 // Sets flow rules for forwarding "packets going to external networks" to gateway nodes.
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700209 if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
sanghofb3b5012016-11-10 15:47:53 +0900210 setExternalConnection(osRouter, osSubnetAdded, true);
sangho6032f342016-07-07 14:32:03 +0900211 }
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700212
sanghofb3b5012016-11-10 15:47:53 +0900213 // Sets flow rules to handle ping to the virtual gateway.
214 Ip4Address vGatewayIp = Ip4Address.valueOf(osSubnetAdded.gatewayIp());
215 gatewayService.getGatewayDeviceIds()
216 .forEach(deviceId -> setGatewayIcmpRule(vGatewayIp, deviceId, true));
217
218 // Sets east-west routing rules for VMs in different Cnode to Switching Table.
219 setForwardingRulesForEastWestRouting(osRouter, osSubnetAdded, true);
220
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900221 }
222
sanghofb3b5012016-11-10 15:47:53 +0900223 private void handleRouterInterfacesRemoved(OpenstackRouter osRouter, OpenstackSubnet osSubnetRemoved) {
224
225 // Removes flow rules for routing among subnets connected to a router.
226 setRoutesAmongSubnets(osRouter, osSubnetRemoved, false);
227
228 // Removes flow rules for forwarding "packets going to external networks" to gateway nodes.
229 if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
230 setExternalConnection(osRouter, osSubnetRemoved, false);
sangho0c2a3da2016-02-16 13:39:07 +0900231 }
232
sanghofb3b5012016-11-10 15:47:53 +0900233 // Removes flow rules to handle ping to the virtual gateway.
234 Ip4Address vGatewayIp = Ip4Address.valueOf(osSubnetRemoved.gatewayIp());
235 gatewayService.getGatewayDeviceIds()
236 .forEach(deviceId -> setGatewayIcmpRule(vGatewayIp, deviceId, false));
237
238 // Removes east-west routing rules for VMs in different Cnode to Switching Table.
239 setForwardingRulesForEastWestRouting(osRouter, osSubnetRemoved, false);
240
241 // Resets east-west routing rules for VMs in different Cnode to Switching Table.
242 routableSubNets(osRouter.id()).stream()
243 .forEach(subnet -> setForwardingRulesForEastWestRouting(osRouter, subnet, true));
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900244 }
245
sanghofb3b5012016-11-10 15:47:53 +0900246 private void setRoutesAmongSubnets(OpenstackRouter osRouter, OpenstackSubnet osSubnetAdded, boolean install) {
sangho3d2bf9c2016-08-26 17:19:55 +0900247 Set<OpenstackSubnet> routableSubNets = routableSubNets(osRouter.id());
248 if (routableSubNets.size() < 2) {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700249 // no other subnet interface is connected to this router, do nothing
250 return;
251 }
252
sangho3d2bf9c2016-08-26 17:19:55 +0900253 Map<String, String> vniMap = new HashMap<>();
Sho SHIMIZU8ebb04a2016-10-06 15:58:29 -0700254 openstackService.networks().forEach(n -> vniMap.put(n.id(), n.segmentId()));
sangho3d2bf9c2016-08-26 17:19:55 +0900255
sanghofb3b5012016-11-10 15:47:53 +0900256 routableSubNets.stream()
257 .filter(subnet -> !subnet.id().equals(osSubnetAdded.id()))
258 .filter(subnet -> vniMap.get(subnet.networkId()) != null)
259 .forEach(subnet -> nodeService.completeNodes().stream()
260 .filter(node -> node.type().equals(COMPUTE))
261 .forEach(node -> {
262 setRoutingRules(node.intBridge(),
263 Integer.parseInt(vniMap.get(subnet.networkId())),
264 Integer.parseInt(vniMap.get(osSubnetAdded.networkId())),
265 subnet, osSubnetAdded, install);
266 setRoutingRules(node.intBridge(),
267 Integer.parseInt(vniMap.get(osSubnetAdded.networkId())),
268 Integer.parseInt(vniMap.get(subnet.networkId())),
269 osSubnetAdded, subnet, install);
270 }
271 ));
Daniel Park81a61a12016-02-26 08:24:44 +0900272 }
273
sanghofb3b5012016-11-10 15:47:53 +0900274 private void setRoutingRules(DeviceId deviceId, int srcVni, int dstVni,
275 OpenstackSubnet subnetSrc, OpenstackSubnet subnetDst, boolean install) {
sangho6032f342016-07-07 14:32:03 +0900276
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700277 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
278 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
sangho6032f342016-07-07 14:32:03 +0900279
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700280 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
sanghofb3b5012016-11-10 15:47:53 +0900281 .matchTunnelId(srcVni)
282 .matchIPSrc(IpPrefix.valueOf(subnetSrc.cidr()))
283 .matchIPDst(IpPrefix.valueOf(subnetDst.cidr()));
sangho6032f342016-07-07 14:32:03 +0900284
sanghofb3b5012016-11-10 15:47:53 +0900285 tBuilder.setTunnelId(dstVni);
sangho6032f342016-07-07 14:32:03 +0900286
sanghofb3b5012016-11-10 15:47:53 +0900287 RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
288 tBuilder.build(), ForwardingObjective.Flag.SPECIFIC, EW_ROUTING_RULE_PRIORITY, install);
289
290 // Flow rules for destination is in different subnet and different node,
291 // because VNI is converted to destination VNI in the source VM node.
292 sBuilder = DefaultTrafficSelector.builder();
293 tBuilder = DefaultTrafficTreatment.builder();
294
295 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
296 .matchTunnelId(dstVni)
297 .matchIPSrc(IpPrefix.valueOf(subnetSrc.cidr()))
298 .matchIPDst(IpPrefix.valueOf(subnetDst.cidr()));
299
300 tBuilder.setTunnelId(dstVni);
301
302 RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
303 tBuilder.build(), ForwardingObjective.Flag.SPECIFIC, EW_ROUTING_RULE_PRIORITY, install);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700304 }
sangho6032f342016-07-07 14:32:03 +0900305
sanghofb3b5012016-11-10 15:47:53 +0900306 private void setExternalConnection(OpenstackRouter osRouter, OpenstackSubnet osSubNet, boolean install) {
307 if (!osRouter.gatewayExternalInfo().isEnablePnat()) {
308 log.debug("Source NAT is disabled");
309 return;
310 }
311
312 //OpenstackSubnet osSubNet = openstackService.subnet(osSubNetId);
313 OpenstackNetwork osNet = openstackService.network(osSubNet.networkId());
314
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700315 nodeService.completeNodes().stream()
316 .filter(node -> node.type().equals(COMPUTE))
sanghofb3b5012016-11-10 15:47:53 +0900317 .forEach(node -> setRulesToGateway(
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700318 node.intBridge(),
319 gatewayService.getGatewayGroupId(node.intBridge()),
sanghofb3b5012016-11-10 15:47:53 +0900320 Long.valueOf(osNet.segmentId()), osSubNet.cidr(), install));
321
322 // Is this for PNAT ??
323 setRulesForGatewayToController(Long.valueOf(osNet.segmentId()), osSubNet.cidr(), install);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700324 }
sangho6032f342016-07-07 14:32:03 +0900325
sanghofb3b5012016-11-10 15:47:53 +0900326 private void setRulesToGateway(DeviceId deviceId, GroupId groupId, long vni, String cidr, boolean install) {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700327 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
328 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
sangho6032f342016-07-07 14:32:03 +0900329
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700330 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
331 .matchTunnelId(vni)
sangho3d2bf9c2016-08-26 17:19:55 +0900332 .matchIPSrc(IpPrefix.valueOf(cidr))
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700333 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
334
335 tBuilder.group(groupId);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700336
sanghofb3b5012016-11-10 15:47:53 +0900337 RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
338 tBuilder.build(), ForwardingObjective.Flag.SPECIFIC, ROUTING_RULE_PRIORITY, install);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700339 }
340
sanghofb3b5012016-11-10 15:47:53 +0900341 private void setRulesForGatewayToController(long vni, String subNetCidr, boolean install) {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700342 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
343 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
344
345 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
346 .matchTunnelId(vni)
sanghofb3b5012016-11-10 15:47:53 +0900347 .matchIPSrc(IpPrefix.valueOf(subNetCidr))
348 .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
349 tBuilder.setOutput(PortNumber.CONTROLLER);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700350
sanghofb3b5012016-11-10 15:47:53 +0900351 gatewayService.getGatewayDeviceIds().forEach(deviceId ->
352 RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
353 tBuilder.build(), ForwardingObjective.Flag.VERSATILE, ROUTING_RULE_PRIORITY, install));
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700354 }
355
sanghofb3b5012016-11-10 15:47:53 +0900356 private void setGatewayIcmpRule(Ip4Address gatewayIp, DeviceId deviceId, boolean install) {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700357 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
358 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
359
360 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
sanghofb3b5012016-11-10 15:47:53 +0900361 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
362 .matchIPDst(gatewayIp.toIpPrefix());
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700363
sanghofb3b5012016-11-10 15:47:53 +0900364 tBuilder.setOutput(PortNumber.CONTROLLER);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700365
sanghofb3b5012016-11-10 15:47:53 +0900366 RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
367 tBuilder.build(), ForwardingObjective.Flag.VERSATILE, GATEWAY_ICMP_PRIORITY, install);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700368 }
369
sanghofb3b5012016-11-10 15:47:53 +0900370 private void setForwardingRulesForEastWestRouting(OpenstackRouter router, OpenstackSubnet subnetAdded,
371 boolean install) {
Daniel Parka8d896c2016-08-26 14:31:33 +0900372
sanghofb3b5012016-11-10 15:47:53 +0900373 Set<OpenstackSubnet> subnets = routableSubNets(router.id());
Daniel Parka8d896c2016-08-26 14:31:33 +0900374
sanghofb3b5012016-11-10 15:47:53 +0900375 Set<Host> hosts = Tools.stream(hostService.getHosts())
376 .filter(h -> getVni(h).equals(openstackService.network(subnetAdded.networkId()).segmentId()))
377 .collect(Collectors.toSet());
378
379 subnets.stream()
380 .filter(subnet -> !subnet.id().equals(subnetAdded.id()))
381 .forEach(subnet -> getHosts(subnet)
382 .forEach(h -> setForwardingRulesAmongHostsInDifferentCnodes(h, hosts, install)));
383 }
384
385 private void setForwardingRulesAmongHostsInDifferentCnodes(Host host, Set<Host> remoteHosts, boolean install) {
386 Ip4Address localVmIp = getIp(host);
387 DeviceId localDeviceId = host.location().deviceId();
388 Optional<IpAddress> localDataIp = nodeService.dataIp(localDeviceId);
389
390 if (!localDataIp.isPresent()) {
391 log.debug("Failed to get data IP for device {}",
392 host.location().deviceId());
393 return;
394 }
395
396 remoteHosts.stream()
397 .filter(remoteHost -> !host.location().deviceId().equals(remoteHost.location().deviceId()))
398 .forEach(remoteVm -> {
399 Optional<IpAddress> remoteDataIp = nodeService.dataIp(remoteVm.location().deviceId());
400 if (remoteDataIp.isPresent()) {
401 setVxLanFlowRule(getVni(remoteVm),
402 localDeviceId,
403 remoteDataIp.get().getIp4Address(),
404 getIp(remoteVm), install);
405
406 setVxLanFlowRule(getVni(host),
407 remoteVm.location().deviceId(),
408 localDataIp.get().getIp4Address(),
409 localVmIp, install);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700410 }
sanghofb3b5012016-11-10 15:47:53 +0900411 });
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700412 }
413
sanghofb3b5012016-11-10 15:47:53 +0900414 private void setVxLanFlowRule(String vni, DeviceId deviceId, Ip4Address remoteIp,
415 Ip4Address vmIp, boolean install) {
416 Optional<PortNumber> tunnelPort = nodeService.tunnelPort(deviceId);
417 if (!tunnelPort.isPresent()) {
418 log.warn("Failed to get tunnel port from {}", deviceId);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700419 return;
sangho6032f342016-07-07 14:32:03 +0900420 }
sanghofb3b5012016-11-10 15:47:53 +0900421
422 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
423 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
424
425 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
426 .matchTunnelId(Long.parseLong(vni))
427 .matchIPDst(vmIp.toIpPrefix());
428 tBuilder.extension(buildExtension(deviceService, deviceId, remoteIp), deviceId)
429 .setOutput(tunnelPort.get());
430
431 RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
432 tBuilder.build(), ForwardingObjective.Flag.SPECIFIC, SWITCHING_RULE_PRIORITY, install);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700433 }
434
sanghofb3b5012016-11-10 15:47:53 +0900435
436 private OpenstackRouter openstackRouter(String routerId) {
437 return openstackService.routers().stream().filter(r ->
438 r.id().equals(routerId)).iterator().next();
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700439 }
440
jskimaa851932016-10-27 17:45:30 +0900441 @Override
442 public void reinstallVmFlow(Host host) {
sanghofb3b5012016-11-10 15:47:53 +0900443 // TODO: implements later
jskimaa851932016-10-27 17:45:30 +0900444 }
445
446 @Override
447 public void purgeVmFlow(Host host) {
sanghofb3b5012016-11-10 15:47:53 +0900448 // TODO: implements later
jskimaa851932016-10-27 17:45:30 +0900449 }
450
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700451 private class InternalNodeListener implements OpenstackNodeListener {
Kyuhwi Choi5e65e2c2016-04-01 11:48:15 +0900452
453 @Override
sangho6032f342016-07-07 14:32:03 +0900454 public void event(OpenstackNodeEvent event) {
455 OpenstackNode node = event.node();
456
457 switch (event.type()) {
458 case COMPLETE:
sanghofb3b5012016-11-10 15:47:53 +0900459 case INCOMPLETE:
sangho6032f342016-07-07 14:32:03 +0900460 log.info("COMPLETE node {} detected", node.hostname());
Hyunsun Moon5aa480b2016-08-03 12:23:14 -0700461 eventExecutor.execute(() -> {
462 if (node.type() == GATEWAY) {
463 GatewayNode gnode = GatewayNode.builder()
464 .gatewayDeviceId(node.intBridge())
465 .dataIpAddress(node.dataIp().getIp4Address())
466 .uplinkIntf(node.externalPortName().get())
467 .build();
468 gatewayService.addGatewayNode(gnode);
469 }
Hyunsun Moon5aa480b2016-08-03 12:23:14 -0700470 });
sanghofb3b5012016-11-10 15:47:53 +0900471 openstackService.routers().stream()
472 .forEach(router -> routableSubNets(router.id()).stream()
473 .forEach(subnet -> handleRouterInterfaces(router, subnet)));
sangho6032f342016-07-07 14:32:03 +0900474 break;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700475 case INIT:
476 case DEVICE_CREATED:
sangho6032f342016-07-07 14:32:03 +0900477 default:
478 break;
Kyuhwi Choi5e65e2c2016-04-01 11:48:15 +0900479 }
sangho6032f342016-07-07 14:32:03 +0900480 }
481 }
sangho0c2a3da2016-02-16 13:39:07 +0900482}