blob: 5616e0ace122bf80ad1ed63aed0078c0d23e779f [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
18import org.onlab.packet.Ethernet;
19import org.onlab.packet.IPv4;
20import org.onlab.packet.Ip4Address;
21import org.onlab.packet.IpAddress;
22import org.onlab.packet.IpPrefix;
23import org.onlab.packet.MacAddress;
24import org.onlab.packet.TCP;
25import org.onlab.packet.TpPort;
26import org.onlab.packet.UDP;
27import org.onosproject.core.ApplicationId;
28import org.onosproject.net.Device;
29import org.onosproject.net.DeviceId;
30import org.onosproject.net.Port;
31import org.onosproject.net.PortNumber;
32import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
33import org.onosproject.net.device.DeviceService;
34import org.onosproject.net.driver.DefaultDriverData;
35import org.onosproject.net.driver.DefaultDriverHandler;
36import org.onosproject.net.driver.Driver;
37import org.onosproject.net.driver.DriverHandler;
38import org.onosproject.net.driver.DriverService;
39import org.onosproject.net.flow.DefaultTrafficSelector;
40import org.onosproject.net.flow.DefaultTrafficTreatment;
41import org.onosproject.net.flow.TrafficSelector;
42import org.onosproject.net.flow.TrafficTreatment;
43import org.onosproject.net.flow.instructions.ExtensionPropertyException;
44import org.onosproject.net.flow.instructions.ExtensionTreatment;
45import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
46import org.onosproject.net.flowobjective.DefaultForwardingObjective;
47import org.onosproject.net.flowobjective.FlowObjectiveService;
48import org.onosproject.net.flowobjective.ForwardingObjective;
49import org.onosproject.net.packet.InboundPacket;
sangho93447f12016-02-24 00:33:22 +090050import org.onosproject.openstackinterface.OpenstackInterfaceService;
51import org.onosproject.openstackinterface.OpenstackPort;
sangho93447f12016-02-24 00:33:22 +090052import org.onosproject.openstackinterface.OpenstackRouterInterface;
53import org.onosproject.openstackinterface.OpenstackSubnet;
Kyuhwi Choiee9e3712016-02-22 22:49:36 +090054import org.onosproject.openstackinterface.OpenstackFloatingIP;
sangho48907542016-03-28 16:07:07 +090055import org.onosproject.openstacknetworking.OpenstackNetworkingConfig;
Kyuhwi Choiee9e3712016-02-22 22:49:36 +090056import org.onosproject.openstacknetworking.OpenstackPortInfo;
sangho0c2a3da2016-02-16 13:39:07 +090057import org.slf4j.Logger;
58import org.slf4j.LoggerFactory;
59
60import java.util.stream.StreamSupport;
61
62import static com.google.common.base.Preconditions.checkNotNull;
63
64/**
65 * Populates Routing Flow Rules.
66 */
67public class OpenstackRoutingRulePopulator {
68
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090069 private final Logger log = LoggerFactory.getLogger(getClass());
sangho0c2a3da2016-02-16 13:39:07 +090070
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090071 private final ApplicationId appId;
72 private final FlowObjectiveService flowObjectiveService;
sangho93447f12016-02-24 00:33:22 +090073 private final OpenstackInterfaceService openstackService;
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090074 private final DeviceService deviceService;
75 private final DriverService driverService;
sangho48907542016-03-28 16:07:07 +090076 private final OpenstackNetworkingConfig config;
sangho0c2a3da2016-02-16 13:39:07 +090077
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090078 private static final String PORTNAME_PREFIX_TUNNEL = "vxlan";
79 private static final String PORTNAME = "portName";
Kyuhwi Choiee9e3712016-02-22 22:49:36 +090080 private static final String PORTNAME_PREFIX_VM = "tap";
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090081
82 private static final String PORTNOTNULL = "Port can not be null";
Kyuhwi Choiee9e3712016-02-22 22:49:36 +090083 private static final String DEVICENOTNULL = "Device can not be null";
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090084 private static final String TUNNEL_DESTINATION = "tunnelDst";
sangho0c2a3da2016-02-16 13:39:07 +090085 private static final int ROUTING_RULE_PRIORITY = 25000;
Kyuhwi Choiee9e3712016-02-22 22:49:36 +090086 private static final int FLOATING_RULE_PRIORITY = 42000;
87 private static final int PNAT_RULE_PRIORITY = 26000;
sangho0c2a3da2016-02-16 13:39:07 +090088 private static final int PNAT_TIMEOUT = 120;
Daniel Park23193902016-03-24 18:17:19 +090089 private static final int PREFIX_LENGTH = 32;
sangho0c2a3da2016-02-16 13:39:07 +090090 private static final MacAddress GATEWAYMAC = MacAddress.valueOf("1f:1f:1f:1f:1f:1f");
91
92 private InboundPacket inboundPacket;
93 private OpenstackPort openstackPort;
94 private int portNum;
95 private MacAddress externalInterface;
96 private MacAddress externalRouter;
sangho0c2a3da2016-02-16 13:39:07 +090097
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090098 /**
99 * The constructor of openstackRoutingRulePopulator.
100 *
101 * @param appId Caller`s appId
102 * @param openstackService OpenstackNetworkingService
103 * @param flowObjectiveService FlowObjectiveService
104 * @param deviceService DeviceService
105 * @param driverService DriverService
Daniel Park81a61a12016-02-26 08:24:44 +0900106 * @param config OpenstackRoutingConfig
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900107 */
sangho93447f12016-02-24 00:33:22 +0900108 public OpenstackRoutingRulePopulator(ApplicationId appId, OpenstackInterfaceService openstackService,
Daniel Park81a61a12016-02-26 08:24:44 +0900109 FlowObjectiveService flowObjectiveService, DeviceService deviceService,
sangho48907542016-03-28 16:07:07 +0900110 DriverService driverService, OpenstackNetworkingConfig config) {
sangho0c2a3da2016-02-16 13:39:07 +0900111 this.appId = appId;
112 this.flowObjectiveService = flowObjectiveService;
Daniel Park81a61a12016-02-26 08:24:44 +0900113 this.openstackService = checkNotNull(openstackService);
sangho0c2a3da2016-02-16 13:39:07 +0900114 this.deviceService = deviceService;
115 this.driverService = driverService;
Daniel Park81a61a12016-02-26 08:24:44 +0900116 this.config = config;
sangho0c2a3da2016-02-16 13:39:07 +0900117 }
118
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900119 /**
120 * Populates flow rules for Pnat configurations.
Daniel Park81a61a12016-02-26 08:24:44 +0900121 *
122 * @param inboundPacket Packet-in event packet
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900123 * @param openstackPort Target VM information
124 * @param portNum Pnat port number
Hyunsun Moon0dba61f2016-03-03 14:05:21 -0800125 * @param externalIp external ip address
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900126 * @param externalInterfaceMacAddress Gateway external interface macaddress
127 * @param externalRouterMacAddress Outer(physical) router`s macaddress
128 */
sangho0c2a3da2016-02-16 13:39:07 +0900129 public void populatePnatFlowRules(InboundPacket inboundPacket, OpenstackPort openstackPort, int portNum,
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900130 Ip4Address externalIp, MacAddress externalInterfaceMacAddress,
131 MacAddress externalRouterMacAddress) {
sangho0c2a3da2016-02-16 13:39:07 +0900132 this.inboundPacket = inboundPacket;
133 this.openstackPort = openstackPort;
134 this.portNum = portNum;
135 this.externalInterface = externalInterfaceMacAddress;
136 this.externalRouter = externalRouterMacAddress;
137
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900138 long vni = getVni(openstackPort.networkId());
sangho0c2a3da2016-02-16 13:39:07 +0900139
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900140 populatePnatIncomingFlowRules(vni, externalIp);
141 populatePnatOutgoingFlowRules(vni, externalIp);
sangho0c2a3da2016-02-16 13:39:07 +0900142 }
143
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900144 private void populatePnatOutgoingFlowRules(long vni, Ip4Address externalIp) {
sangho0c2a3da2016-02-16 13:39:07 +0900145 IPv4 iPacket = (IPv4) inboundPacket.parsed().getPayload();
146
147 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
148 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
149 .matchIPProtocol(iPacket.getProtocol())
150 .matchTunnelId(vni)
151 .matchIPSrc(IpPrefix.valueOf(iPacket.getSourceAddress(), 32))
152 .matchIPDst(IpPrefix.valueOf(iPacket.getDestinationAddress(), 32));
153
154 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
155 tBuilder.setEthSrc(externalInterface)
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900156 .setEthDst(externalRouter)
157 .setIpSrc(externalIp);
sangho0c2a3da2016-02-16 13:39:07 +0900158
159 switch (iPacket.getProtocol()) {
160 case IPv4.PROTOCOL_TCP:
161 TCP tcpPacket = (TCP) iPacket.getPayload();
162 sBuilder.matchTcpSrc(TpPort.tpPort(tcpPacket.getSourcePort()))
163 .matchTcpDst(TpPort.tpPort(tcpPacket.getDestinationPort()));
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900164 tBuilder.setTcpSrc(TpPort.tpPort(portNum));
sangho0c2a3da2016-02-16 13:39:07 +0900165 break;
166 case IPv4.PROTOCOL_UDP:
167 UDP udpPacket = (UDP) iPacket.getPayload();
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900168 sBuilder.matchUdpSrc(TpPort.tpPort(udpPacket.getSourcePort()))
sangho0c2a3da2016-02-16 13:39:07 +0900169 .matchUdpDst(TpPort.tpPort(udpPacket.getDestinationPort()));
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900170 tBuilder.setUdpSrc(TpPort.tpPort(portNum));
sangho0c2a3da2016-02-16 13:39:07 +0900171 break;
172 default:
Daniel Park81a61a12016-02-26 08:24:44 +0900173 log.debug("Unsupported IPv4 protocol {}");
sangho0c2a3da2016-02-16 13:39:07 +0900174 break;
175 }
176
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900177 Port port = checkNotNull(getPortOfExternalInterface(), PORTNOTNULL);
sangho0c2a3da2016-02-16 13:39:07 +0900178 tBuilder.setOutput(port.number());
179
180 ForwardingObjective fo = DefaultForwardingObjective.builder()
181 .withSelector(sBuilder.build())
182 .withTreatment(tBuilder.build())
183 .withFlag(ForwardingObjective.Flag.VERSATILE)
184 .withPriority(PNAT_RULE_PRIORITY)
185 .makeTemporary(PNAT_TIMEOUT)
186 .fromApp(appId)
187 .add();
188
189 flowObjectiveService.forward(inboundPacket.receivedFrom().deviceId(), fo);
190 }
191
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900192 private Port getPortOfExternalInterface() {
193 return deviceService.getPorts(getGatewayNode().id()).stream()
Daniel Park81a61a12016-02-26 08:24:44 +0900194 .filter(p -> p.annotations().value(PORTNAME).equals(config.gatewayExternalInterfaceName()))
sangho0c2a3da2016-02-16 13:39:07 +0900195 .findAny().orElse(null);
196 }
197
198
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900199 private void populatePnatIncomingFlowRules(long vni, Ip4Address externalIp) {
sangho0c2a3da2016-02-16 13:39:07 +0900200 IPv4 iPacket = (IPv4) inboundPacket.parsed().getPayload();
201 DeviceId deviceId = inboundPacket.receivedFrom().deviceId();
202
203 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
204 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
205 .matchIPProtocol(iPacket.getProtocol())
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900206 .matchIPDst(IpPrefix.valueOf(externalIp, 32))
sangho0c2a3da2016-02-16 13:39:07 +0900207 .matchIPSrc(IpPrefix.valueOf(iPacket.getDestinationAddress(), 32));
208
209 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
210 tBuilder.setTunnelId(vni)
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900211 .setEthDst(inboundPacket.parsed().getSourceMAC())
sangho0c2a3da2016-02-16 13:39:07 +0900212 .setIpDst(IpAddress.valueOf(iPacket.getSourceAddress()));
213
214 switch (iPacket.getProtocol()) {
215 case IPv4.PROTOCOL_TCP:
216 TCP tcpPacket = (TCP) iPacket.getPayload();
217 sBuilder.matchTcpSrc(TpPort.tpPort(tcpPacket.getDestinationPort()))
218 .matchTcpDst(TpPort.tpPort(portNum));
219 tBuilder.setTcpDst(TpPort.tpPort(tcpPacket.getSourcePort()));
220 break;
221 case IPv4.PROTOCOL_UDP:
222 UDP udpPacket = (UDP) iPacket.getPayload();
223 sBuilder.matchUdpSrc(TpPort.tpPort(udpPacket.getDestinationPort()))
224 .matchUdpDst(TpPort.tpPort(portNum));
225 tBuilder.setUdpDst(TpPort.tpPort(udpPacket.getSourcePort()));
226 break;
227 default:
228 break;
229 }
230
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900231 tBuilder.extension(buildNiciraExtenstion(deviceId, getHostIpfromOpenstackPort(openstackPort)), deviceId)
sangho0c2a3da2016-02-16 13:39:07 +0900232 .setOutput(getTunnelPort(deviceId));
233
234 ForwardingObjective fo = DefaultForwardingObjective.builder()
235 .withSelector(sBuilder.build())
236 .withTreatment(tBuilder.build())
237 .withFlag(ForwardingObjective.Flag.VERSATILE)
238 .withPriority(PNAT_RULE_PRIORITY)
239 .makeTemporary(PNAT_TIMEOUT)
240 .fromApp(appId)
241 .add();
242
243 flowObjectiveService.forward(inboundPacket.receivedFrom().deviceId(), fo);
244 }
245
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900246 private Ip4Address getHostIpfromOpenstackPort(OpenstackPort openstackPort) {
247 Device device = getDevicefromOpenstackPort(openstackPort);
Daniel Park23193902016-03-24 18:17:19 +0900248 return config.nodes().get(device.id());
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900249 }
Daniel Park81a61a12016-02-26 08:24:44 +0900250
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900251 private Device getDevicefromOpenstackPort(OpenstackPort openstackPort) {
252 String openstackPortName = PORTNAME_PREFIX_VM + openstackPort.id().substring(0, 11);
253 Device device = StreamSupport.stream(deviceService.getDevices().spliterator(), false)
254 .filter(d -> findPortinDevice(d, openstackPortName))
255 .findAny()
256 .orElse(null);
257 checkNotNull(device, DEVICENOTNULL);
258 return device;
259 }
260
261 private boolean findPortinDevice(Device d, String openstackPortName) {
262 Port port = deviceService.getPorts(d.id())
263 .stream()
264 .filter(p -> p.isEnabled() && p.annotations().value(PORTNAME).equals(openstackPortName))
265 .findAny()
266 .orElse(null);
Daniel Park23193902016-03-24 18:17:19 +0900267 return port != null;
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900268 }
269
270 /**
271 * Builds NiciraExtension for tagging remoteIp of vxlan.
272 *
273 * @param id Device Id of vxlan source device
274 * @param hostIp Remote Ip of vxlan destination device
275 * @return NiciraExtension Treatment
276 */
Daniel Park81a61a12016-02-26 08:24:44 +0900277 public ExtensionTreatment buildNiciraExtenstion(DeviceId id, Ip4Address hostIp) {
sangho0c2a3da2016-02-16 13:39:07 +0900278 Driver driver = driverService.getDriver(id);
279 DriverHandler driverHandler = new DefaultDriverHandler(new DefaultDriverData(driver, id));
280 ExtensionTreatmentResolver resolver = driverHandler.behaviour(ExtensionTreatmentResolver.class);
281
282 ExtensionTreatment extensionInstruction =
283 resolver.getExtensionInstruction(
284 ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST.type());
285
286 try {
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900287 extensionInstruction.setPropertyValue(TUNNEL_DESTINATION, hostIp);
sangho0c2a3da2016-02-16 13:39:07 +0900288 } catch (ExtensionPropertyException e) {
289 log.error("Error setting Nicira extension setting {}", e);
290 }
291
292 return extensionInstruction;
293 }
294
Daniel Park81a61a12016-02-26 08:24:44 +0900295 /**
296 * Returns port number of vxlan tunnel.
297 *
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900298 * @param deviceId Target Device Id
299 * @return PortNumber
Daniel Park81a61a12016-02-26 08:24:44 +0900300 */
301 public PortNumber getTunnelPort(DeviceId deviceId) {
sangho0c2a3da2016-02-16 13:39:07 +0900302 Port port = deviceService.getPorts(deviceId).stream()
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900303 .filter(p -> p.annotations().value(PORTNAME).equals(PORTNAME_PREFIX_TUNNEL))
sangho0c2a3da2016-02-16 13:39:07 +0900304 .findAny().orElse(null);
305
306 if (port == null) {
307 log.error("No TunnelPort was created.");
308 return null;
309 }
310 return port.number();
311
312 }
313
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900314 /**
315 * Populates flow rules from openstackComputeNode to GatewayNode.
316 *
317 * @param vni Target network
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900318 */
Daniel Park23193902016-03-24 18:17:19 +0900319 public void populateExternalRules(long vni) {
sangho0c2a3da2016-02-16 13:39:07 +0900320
321 // 1. computeNode to gateway
322 populateComputeNodeRules(vni);
323 // 2. gatewayNode to controller
324 populateRuleGatewaytoController(vni);
325 }
326
327 private void populateRuleGatewaytoController(long vni) {
328 Device gatewayDevice = getGatewayNode();
329 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
330 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
331
332 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
333 .matchTunnelId(vni)
334 .matchEthDst(GATEWAYMAC);
335 tBuilder.setOutput(PortNumber.CONTROLLER);
336
337 ForwardingObjective fo = DefaultForwardingObjective.builder()
338 .withSelector(sBuilder.build())
339 .withTreatment(tBuilder.build())
340 .withFlag(ForwardingObjective.Flag.VERSATILE)
341 .withPriority(ROUTING_RULE_PRIORITY)
342 .fromApp(appId)
343 .add();
344
345 flowObjectiveService.forward(gatewayDevice.id(), fo);
346 }
347
348 private void populateComputeNodeRules(long vni) {
349 Device gatewayDevice = getGatewayNode();
350
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900351 StreamSupport.stream(deviceService.getDevices().spliterator(), false)
sangho0c2a3da2016-02-16 13:39:07 +0900352 .filter(d -> !checkGatewayNode(d.id()))
353 .forEach(d -> populateRuleToGateway(d, gatewayDevice, vni));
sangho0c2a3da2016-02-16 13:39:07 +0900354 }
355
356 private void populateRuleToGateway(Device d, Device gatewayDevice, long vni) {
357 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
358 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
359
360 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
361 .matchTunnelId(vni)
362 .matchEthDst(GATEWAYMAC);
Daniel Park23193902016-03-24 18:17:19 +0900363 tBuilder.extension(buildNiciraExtenstion(d.id(), config.nodes().get(gatewayDevice.id())), d.id())
sangho0c2a3da2016-02-16 13:39:07 +0900364 .setOutput(getTunnelPort(d.id()));
365
366 ForwardingObjective fo = DefaultForwardingObjective.builder()
367 .withSelector(sBuilder.build())
368 .withTreatment(tBuilder.build())
369 .withFlag(ForwardingObjective.Flag.SPECIFIC)
370 .withPriority(ROUTING_RULE_PRIORITY)
371 .fromApp(appId)
372 .add();
373
374 flowObjectiveService.forward(d.id(), fo);
375 }
376
sangho0c2a3da2016-02-16 13:39:07 +0900377 private Device getGatewayNode() {
Daniel Park81a61a12016-02-26 08:24:44 +0900378 return checkNotNull(deviceService.getDevice(DeviceId.deviceId(config.gatewayBridgeId())));
sangho0c2a3da2016-02-16 13:39:07 +0900379 }
380
381 private boolean checkGatewayNode(DeviceId deviceId) {
Daniel Park81a61a12016-02-26 08:24:44 +0900382 return deviceId.toString().equals(config.gatewayBridgeId());
sangho0c2a3da2016-02-16 13:39:07 +0900383 }
384
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900385 private long getVni(String netId) {
386 return Long.parseLong(openstackService.network(netId).segmentId());
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900387 }
388
389 /**
390 * Remove flow rules for external connection.
391 *
392 * @param routerInterface Corresponding routerInterface
393 */
sangho0c2a3da2016-02-16 13:39:07 +0900394 public void removeExternalRules(OpenstackRouterInterface routerInterface) {
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900395 OpenstackSubnet openstackSubnet = openstackService.subnet(routerInterface.subnetId());
sangho0c2a3da2016-02-16 13:39:07 +0900396 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
397 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900398 .matchTunnelId(getVni(openstackSubnet.networkId()))
sangho0c2a3da2016-02-16 13:39:07 +0900399 .matchEthDst(GATEWAYMAC);
400
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900401 StreamSupport.stream(deviceService.getDevices().spliterator(), false)
sangho0c2a3da2016-02-16 13:39:07 +0900402 .forEach(d -> {
Daniel Park23193902016-03-24 18:17:19 +0900403 ForwardingObjective.Flag flag = checkGatewayNode(d.id()) ?
404 ForwardingObjective.Flag.VERSATILE : ForwardingObjective.Flag.SPECIFIC;
405
406 removeRule(d.id(), sBuilder, flag, ROUTING_RULE_PRIORITY);
sangho0c2a3da2016-02-16 13:39:07 +0900407 });
408
409 }
410
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900411 private void removeRule(DeviceId id, TrafficSelector.Builder sBuilder,
412 ForwardingObjective.Flag flag, int priority) {
sangho0c2a3da2016-02-16 13:39:07 +0900413 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
414
415 ForwardingObjective fo = DefaultForwardingObjective.builder()
416 .withSelector(sBuilder.build())
417 .withTreatment(tBuilder.build())
418 .withFlag(flag)
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900419 .withPriority(priority)
sangho0c2a3da2016-02-16 13:39:07 +0900420 .fromApp(appId)
421 .remove();
422
423 flowObjectiveService.forward(id, fo);
424 }
425
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900426 /**
427 * Populates flow rules for floatingIp configuration.
428 *
429 * @param floatingIP Corresponding floating ip information
430 */
431 public void populateFloatingIpRules(OpenstackFloatingIP floatingIP) {
432 OpenstackPort port = openstackService.port(floatingIP.portId());
433 //1. incoming rules
434 populateFloatingIpIncomingRules(floatingIP, port);
435 //2. outgoing rules
436 populateFloatingIpOutgoingRules(floatingIP, port);
437 }
438
439 private void populateFloatingIpIncomingRules(OpenstackFloatingIP floatingIP, OpenstackPort port) {
440 DeviceId portDeviceId = getDevicefromOpenstackPort(port).id();
441 Device gatewayNode = getGatewayNode();
442 Device portNode = deviceService.getDevice(portDeviceId);
443
444 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
445 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
446
447 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
Daniel Park23193902016-03-24 18:17:19 +0900448 .matchIPDst(IpPrefix.valueOf(floatingIP.floatingIpAddress(), PREFIX_LENGTH));
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900449
450 tBuilder.setEthSrc(MacAddress.valueOf(config.gatewayExternalInterfaceMac()))
451 .setEthDst(port.macAddress())
452 .setIpDst(floatingIP.fixedIpAddress())
453 .setTunnelId(getVni(port.networkId()))
Daniel Park23193902016-03-24 18:17:19 +0900454 .extension(buildNiciraExtenstion(gatewayNode.id(),
455 config.nodes().get(portNode.id())), gatewayNode.id())
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900456 .setOutput(getTunnelPort(gatewayNode.id()));
457
458 ForwardingObjective fo = DefaultForwardingObjective.builder()
459 .withSelector(sBuilder.build())
460 .withTreatment(tBuilder.build())
461 .withFlag(ForwardingObjective.Flag.VERSATILE)
462 .withPriority(FLOATING_RULE_PRIORITY)
463 .fromApp(appId)
464 .add();
465
466 flowObjectiveService.forward(getGatewayNode().id(), fo);
467
468 }
469
470 private void populateFloatingIpOutgoingRules(OpenstackFloatingIP floatingIP, OpenstackPort port) {
471 Port outputPort = checkNotNull(getPortOfExternalInterface(), PORTNOTNULL);
472
473 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
474 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
475
476 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
477 .matchTunnelId(getVni(port.networkId()))
478 .matchIPSrc(IpPrefix.valueOf(floatingIP.fixedIpAddress(), 32));
479
480 tBuilder.setIpSrc(floatingIP.floatingIpAddress())
481 .setEthSrc(MacAddress.valueOf(config.gatewayExternalInterfaceMac()))
482 .setEthDst(MacAddress.valueOf(config.physicalRouterMac()))
483 .setOutput(outputPort.number());
484
485 ForwardingObjective fo = DefaultForwardingObjective.builder()
486 .withSelector(sBuilder.build())
487 .withTreatment(tBuilder.build())
488 .withFlag(ForwardingObjective.Flag.VERSATILE)
489 .withPriority(FLOATING_RULE_PRIORITY)
490 .fromApp(appId)
491 .add();
492
493 flowObjectiveService.forward(getGatewayNode().id(), fo);
494 }
495
496 /**
497 * Removes flow rules for floating ip configuration.
498 *
499 * @param floatingIP Corresponding floating ip information
Ray Milkeyd4334db2016-04-05 17:39:44 -0700500 * @param portInfo stored information about deleted vm
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900501 */
502 public void removeFloatingIpRules(OpenstackFloatingIP floatingIP, OpenstackPortInfo portInfo) {
503 TrafficSelector.Builder sOutgoingBuilder = DefaultTrafficSelector.builder();
504 TrafficSelector.Builder sIncomingBuilder = DefaultTrafficSelector.builder();
505
506 sOutgoingBuilder.matchEthType(Ethernet.TYPE_IPV4)
507 .matchTunnelId(portInfo.vni())
Daniel Park23193902016-03-24 18:17:19 +0900508 .matchIPSrc(IpPrefix.valueOf(portInfo.ip(), PREFIX_LENGTH));
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900509
510 sIncomingBuilder.matchEthType(Ethernet.TYPE_IPV4)
Daniel Park23193902016-03-24 18:17:19 +0900511 .matchIPDst(IpPrefix.valueOf(floatingIP.floatingIpAddress(), PREFIX_LENGTH));
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900512
513 removeRule(getGatewayNode().id(), sOutgoingBuilder, ForwardingObjective.Flag.VERSATILE, FLOATING_RULE_PRIORITY);
514 removeRule(getGatewayNode().id(), sIncomingBuilder, ForwardingObjective.Flag.VERSATILE, FLOATING_RULE_PRIORITY);
515 }
516
sangho0c2a3da2016-02-16 13:39:07 +0900517}