blob: d8d56e6eae17840376b07116710567b607bf921e [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;
55import org.onosproject.openstacknetworking.OpenstackPortInfo;
sangho0c2a3da2016-02-16 13:39:07 +090056import org.slf4j.Logger;
57import org.slf4j.LoggerFactory;
58
59import java.util.stream.StreamSupport;
60
61import static com.google.common.base.Preconditions.checkNotNull;
62
63/**
64 * Populates Routing Flow Rules.
65 */
66public class OpenstackRoutingRulePopulator {
67
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090068 private final Logger log = LoggerFactory.getLogger(getClass());
sangho0c2a3da2016-02-16 13:39:07 +090069
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090070 private final ApplicationId appId;
71 private final FlowObjectiveService flowObjectiveService;
sangho93447f12016-02-24 00:33:22 +090072 private final OpenstackInterfaceService openstackService;
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090073 private final DeviceService deviceService;
74 private final DriverService driverService;
Daniel Park81a61a12016-02-26 08:24:44 +090075 private final OpenstackRoutingConfig config;
sangho0c2a3da2016-02-16 13:39:07 +090076
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090077 private static final String PORTNAME_PREFIX_TUNNEL = "vxlan";
78 private static final String PORTNAME = "portName";
Kyuhwi Choiee9e3712016-02-22 22:49:36 +090079 private static final String PORTNAME_PREFIX_VM = "tap";
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090080
81 private static final String PORTNOTNULL = "Port can not be null";
Kyuhwi Choiee9e3712016-02-22 22:49:36 +090082 private static final String DEVICENOTNULL = "Device can not be null";
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090083 private static final String TUNNEL_DESTINATION = "tunnelDst";
sangho0c2a3da2016-02-16 13:39:07 +090084 private static final int ROUTING_RULE_PRIORITY = 25000;
Kyuhwi Choiee9e3712016-02-22 22:49:36 +090085 private static final int FLOATING_RULE_PRIORITY = 42000;
86 private static final int PNAT_RULE_PRIORITY = 26000;
sangho0c2a3da2016-02-16 13:39:07 +090087 private static final int PNAT_TIMEOUT = 120;
Daniel Park23193902016-03-24 18:17:19 +090088 private static final int PREFIX_LENGTH = 32;
sangho0c2a3da2016-02-16 13:39:07 +090089 private static final MacAddress GATEWAYMAC = MacAddress.valueOf("1f:1f:1f:1f:1f:1f");
90
91 private InboundPacket inboundPacket;
92 private OpenstackPort openstackPort;
93 private int portNum;
94 private MacAddress externalInterface;
95 private MacAddress externalRouter;
sangho0c2a3da2016-02-16 13:39:07 +090096
Kyuhwi Choie2b37e32016-02-05 14:04:14 +090097 /**
98 * The constructor of openstackRoutingRulePopulator.
99 *
100 * @param appId Caller`s appId
101 * @param openstackService OpenstackNetworkingService
102 * @param flowObjectiveService FlowObjectiveService
103 * @param deviceService DeviceService
104 * @param driverService DriverService
Daniel Park81a61a12016-02-26 08:24:44 +0900105 * @param config OpenstackRoutingConfig
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900106 */
sangho93447f12016-02-24 00:33:22 +0900107 public OpenstackRoutingRulePopulator(ApplicationId appId, OpenstackInterfaceService openstackService,
Daniel Park81a61a12016-02-26 08:24:44 +0900108 FlowObjectiveService flowObjectiveService, DeviceService deviceService,
109 DriverService driverService, OpenstackRoutingConfig config) {
sangho0c2a3da2016-02-16 13:39:07 +0900110 this.appId = appId;
111 this.flowObjectiveService = flowObjectiveService;
Daniel Park81a61a12016-02-26 08:24:44 +0900112 this.openstackService = checkNotNull(openstackService);
sangho0c2a3da2016-02-16 13:39:07 +0900113 this.deviceService = deviceService;
114 this.driverService = driverService;
Daniel Park81a61a12016-02-26 08:24:44 +0900115 this.config = config;
sangho0c2a3da2016-02-16 13:39:07 +0900116 }
117
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900118 /**
119 * Populates flow rules for Pnat configurations.
Daniel Park81a61a12016-02-26 08:24:44 +0900120 *
121 * @param inboundPacket Packet-in event packet
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900122 * @param openstackPort Target VM information
123 * @param portNum Pnat port number
Hyunsun Moon0dba61f2016-03-03 14:05:21 -0800124 * @param externalIp external ip address
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900125 * @param externalInterfaceMacAddress Gateway external interface macaddress
126 * @param externalRouterMacAddress Outer(physical) router`s macaddress
127 */
sangho0c2a3da2016-02-16 13:39:07 +0900128 public void populatePnatFlowRules(InboundPacket inboundPacket, OpenstackPort openstackPort, int portNum,
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900129 Ip4Address externalIp, MacAddress externalInterfaceMacAddress,
130 MacAddress externalRouterMacAddress) {
sangho0c2a3da2016-02-16 13:39:07 +0900131 this.inboundPacket = inboundPacket;
132 this.openstackPort = openstackPort;
133 this.portNum = portNum;
134 this.externalInterface = externalInterfaceMacAddress;
135 this.externalRouter = externalRouterMacAddress;
136
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900137 long vni = getVni(openstackPort.networkId());
sangho0c2a3da2016-02-16 13:39:07 +0900138
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900139 populatePnatIncomingFlowRules(vni, externalIp);
140 populatePnatOutgoingFlowRules(vni, externalIp);
sangho0c2a3da2016-02-16 13:39:07 +0900141 }
142
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900143 private void populatePnatOutgoingFlowRules(long vni, Ip4Address externalIp) {
sangho0c2a3da2016-02-16 13:39:07 +0900144 IPv4 iPacket = (IPv4) inboundPacket.parsed().getPayload();
145
146 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
147 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
148 .matchIPProtocol(iPacket.getProtocol())
149 .matchTunnelId(vni)
150 .matchIPSrc(IpPrefix.valueOf(iPacket.getSourceAddress(), 32))
151 .matchIPDst(IpPrefix.valueOf(iPacket.getDestinationAddress(), 32));
152
153 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
154 tBuilder.setEthSrc(externalInterface)
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900155 .setEthDst(externalRouter)
156 .setIpSrc(externalIp);
sangho0c2a3da2016-02-16 13:39:07 +0900157
158 switch (iPacket.getProtocol()) {
159 case IPv4.PROTOCOL_TCP:
160 TCP tcpPacket = (TCP) iPacket.getPayload();
161 sBuilder.matchTcpSrc(TpPort.tpPort(tcpPacket.getSourcePort()))
162 .matchTcpDst(TpPort.tpPort(tcpPacket.getDestinationPort()));
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900163 tBuilder.setTcpSrc(TpPort.tpPort(portNum));
sangho0c2a3da2016-02-16 13:39:07 +0900164 break;
165 case IPv4.PROTOCOL_UDP:
166 UDP udpPacket = (UDP) iPacket.getPayload();
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900167 sBuilder.matchUdpSrc(TpPort.tpPort(udpPacket.getSourcePort()))
sangho0c2a3da2016-02-16 13:39:07 +0900168 .matchUdpDst(TpPort.tpPort(udpPacket.getDestinationPort()));
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900169 tBuilder.setUdpSrc(TpPort.tpPort(portNum));
sangho0c2a3da2016-02-16 13:39:07 +0900170 break;
171 default:
Daniel Park81a61a12016-02-26 08:24:44 +0900172 log.debug("Unsupported IPv4 protocol {}");
sangho0c2a3da2016-02-16 13:39:07 +0900173 break;
174 }
175
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900176 Port port = checkNotNull(getPortOfExternalInterface(), PORTNOTNULL);
sangho0c2a3da2016-02-16 13:39:07 +0900177 tBuilder.setOutput(port.number());
178
179 ForwardingObjective fo = DefaultForwardingObjective.builder()
180 .withSelector(sBuilder.build())
181 .withTreatment(tBuilder.build())
182 .withFlag(ForwardingObjective.Flag.VERSATILE)
183 .withPriority(PNAT_RULE_PRIORITY)
184 .makeTemporary(PNAT_TIMEOUT)
185 .fromApp(appId)
186 .add();
187
188 flowObjectiveService.forward(inboundPacket.receivedFrom().deviceId(), fo);
189 }
190
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900191 private Port getPortOfExternalInterface() {
192 return deviceService.getPorts(getGatewayNode().id()).stream()
Daniel Park81a61a12016-02-26 08:24:44 +0900193 .filter(p -> p.annotations().value(PORTNAME).equals(config.gatewayExternalInterfaceName()))
sangho0c2a3da2016-02-16 13:39:07 +0900194 .findAny().orElse(null);
195 }
196
197
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900198 private void populatePnatIncomingFlowRules(long vni, Ip4Address externalIp) {
sangho0c2a3da2016-02-16 13:39:07 +0900199 IPv4 iPacket = (IPv4) inboundPacket.parsed().getPayload();
200 DeviceId deviceId = inboundPacket.receivedFrom().deviceId();
201
202 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
203 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
204 .matchIPProtocol(iPacket.getProtocol())
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900205 .matchIPDst(IpPrefix.valueOf(externalIp, 32))
sangho0c2a3da2016-02-16 13:39:07 +0900206 .matchIPSrc(IpPrefix.valueOf(iPacket.getDestinationAddress(), 32));
207
208 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
209 tBuilder.setTunnelId(vni)
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900210 .setEthDst(inboundPacket.parsed().getSourceMAC())
sangho0c2a3da2016-02-16 13:39:07 +0900211 .setIpDst(IpAddress.valueOf(iPacket.getSourceAddress()));
212
213 switch (iPacket.getProtocol()) {
214 case IPv4.PROTOCOL_TCP:
215 TCP tcpPacket = (TCP) iPacket.getPayload();
216 sBuilder.matchTcpSrc(TpPort.tpPort(tcpPacket.getDestinationPort()))
217 .matchTcpDst(TpPort.tpPort(portNum));
218 tBuilder.setTcpDst(TpPort.tpPort(tcpPacket.getSourcePort()));
219 break;
220 case IPv4.PROTOCOL_UDP:
221 UDP udpPacket = (UDP) iPacket.getPayload();
222 sBuilder.matchUdpSrc(TpPort.tpPort(udpPacket.getDestinationPort()))
223 .matchUdpDst(TpPort.tpPort(portNum));
224 tBuilder.setUdpDst(TpPort.tpPort(udpPacket.getSourcePort()));
225 break;
226 default:
227 break;
228 }
229
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900230 tBuilder.extension(buildNiciraExtenstion(deviceId, getHostIpfromOpenstackPort(openstackPort)), deviceId)
sangho0c2a3da2016-02-16 13:39:07 +0900231 .setOutput(getTunnelPort(deviceId));
232
233 ForwardingObjective fo = DefaultForwardingObjective.builder()
234 .withSelector(sBuilder.build())
235 .withTreatment(tBuilder.build())
236 .withFlag(ForwardingObjective.Flag.VERSATILE)
237 .withPriority(PNAT_RULE_PRIORITY)
238 .makeTemporary(PNAT_TIMEOUT)
239 .fromApp(appId)
240 .add();
241
242 flowObjectiveService.forward(inboundPacket.receivedFrom().deviceId(), fo);
243 }
244
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900245 private Ip4Address getHostIpfromOpenstackPort(OpenstackPort openstackPort) {
246 Device device = getDevicefromOpenstackPort(openstackPort);
Daniel Park23193902016-03-24 18:17:19 +0900247 return config.nodes().get(device.id());
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900248 }
Daniel Park81a61a12016-02-26 08:24:44 +0900249
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900250 private Device getDevicefromOpenstackPort(OpenstackPort openstackPort) {
251 String openstackPortName = PORTNAME_PREFIX_VM + openstackPort.id().substring(0, 11);
252 Device device = StreamSupport.stream(deviceService.getDevices().spliterator(), false)
253 .filter(d -> findPortinDevice(d, openstackPortName))
254 .findAny()
255 .orElse(null);
256 checkNotNull(device, DEVICENOTNULL);
257 return device;
258 }
259
260 private boolean findPortinDevice(Device d, String openstackPortName) {
261 Port port = deviceService.getPorts(d.id())
262 .stream()
263 .filter(p -> p.isEnabled() && p.annotations().value(PORTNAME).equals(openstackPortName))
264 .findAny()
265 .orElse(null);
Daniel Park23193902016-03-24 18:17:19 +0900266 return port != null;
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900267 }
268
269 /**
270 * Builds NiciraExtension for tagging remoteIp of vxlan.
271 *
272 * @param id Device Id of vxlan source device
273 * @param hostIp Remote Ip of vxlan destination device
274 * @return NiciraExtension Treatment
275 */
Daniel Park81a61a12016-02-26 08:24:44 +0900276 public ExtensionTreatment buildNiciraExtenstion(DeviceId id, Ip4Address hostIp) {
sangho0c2a3da2016-02-16 13:39:07 +0900277 Driver driver = driverService.getDriver(id);
278 DriverHandler driverHandler = new DefaultDriverHandler(new DefaultDriverData(driver, id));
279 ExtensionTreatmentResolver resolver = driverHandler.behaviour(ExtensionTreatmentResolver.class);
280
281 ExtensionTreatment extensionInstruction =
282 resolver.getExtensionInstruction(
283 ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST.type());
284
285 try {
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900286 extensionInstruction.setPropertyValue(TUNNEL_DESTINATION, hostIp);
sangho0c2a3da2016-02-16 13:39:07 +0900287 } catch (ExtensionPropertyException e) {
288 log.error("Error setting Nicira extension setting {}", e);
289 }
290
291 return extensionInstruction;
292 }
293
Daniel Park81a61a12016-02-26 08:24:44 +0900294 /**
295 * Returns port number of vxlan tunnel.
296 *
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900297 * @param deviceId Target Device Id
298 * @return PortNumber
Daniel Park81a61a12016-02-26 08:24:44 +0900299 */
300 public PortNumber getTunnelPort(DeviceId deviceId) {
sangho0c2a3da2016-02-16 13:39:07 +0900301 Port port = deviceService.getPorts(deviceId).stream()
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900302 .filter(p -> p.annotations().value(PORTNAME).equals(PORTNAME_PREFIX_TUNNEL))
sangho0c2a3da2016-02-16 13:39:07 +0900303 .findAny().orElse(null);
304
305 if (port == null) {
306 log.error("No TunnelPort was created.");
307 return null;
308 }
309 return port.number();
310
311 }
312
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900313 /**
314 * Populates flow rules from openstackComputeNode to GatewayNode.
315 *
316 * @param vni Target network
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900317 */
Daniel Park23193902016-03-24 18:17:19 +0900318 public void populateExternalRules(long vni) {
sangho0c2a3da2016-02-16 13:39:07 +0900319
320 // 1. computeNode to gateway
321 populateComputeNodeRules(vni);
322 // 2. gatewayNode to controller
323 populateRuleGatewaytoController(vni);
324 }
325
326 private void populateRuleGatewaytoController(long vni) {
327 Device gatewayDevice = getGatewayNode();
328 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
329 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
330
331 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
332 .matchTunnelId(vni)
333 .matchEthDst(GATEWAYMAC);
334 tBuilder.setOutput(PortNumber.CONTROLLER);
335
336 ForwardingObjective fo = DefaultForwardingObjective.builder()
337 .withSelector(sBuilder.build())
338 .withTreatment(tBuilder.build())
339 .withFlag(ForwardingObjective.Flag.VERSATILE)
340 .withPriority(ROUTING_RULE_PRIORITY)
341 .fromApp(appId)
342 .add();
343
344 flowObjectiveService.forward(gatewayDevice.id(), fo);
345 }
346
347 private void populateComputeNodeRules(long vni) {
348 Device gatewayDevice = getGatewayNode();
349
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900350 StreamSupport.stream(deviceService.getDevices().spliterator(), false)
sangho0c2a3da2016-02-16 13:39:07 +0900351 .filter(d -> !checkGatewayNode(d.id()))
352 .forEach(d -> populateRuleToGateway(d, gatewayDevice, vni));
sangho0c2a3da2016-02-16 13:39:07 +0900353 }
354
355 private void populateRuleToGateway(Device d, Device gatewayDevice, long vni) {
356 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
357 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
358
359 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
360 .matchTunnelId(vni)
361 .matchEthDst(GATEWAYMAC);
Daniel Park23193902016-03-24 18:17:19 +0900362 tBuilder.extension(buildNiciraExtenstion(d.id(), config.nodes().get(gatewayDevice.id())), d.id())
sangho0c2a3da2016-02-16 13:39:07 +0900363 .setOutput(getTunnelPort(d.id()));
364
365 ForwardingObjective fo = DefaultForwardingObjective.builder()
366 .withSelector(sBuilder.build())
367 .withTreatment(tBuilder.build())
368 .withFlag(ForwardingObjective.Flag.SPECIFIC)
369 .withPriority(ROUTING_RULE_PRIORITY)
370 .fromApp(appId)
371 .add();
372
373 flowObjectiveService.forward(d.id(), fo);
374 }
375
sangho0c2a3da2016-02-16 13:39:07 +0900376 private Device getGatewayNode() {
Daniel Park81a61a12016-02-26 08:24:44 +0900377 return checkNotNull(deviceService.getDevice(DeviceId.deviceId(config.gatewayBridgeId())));
sangho0c2a3da2016-02-16 13:39:07 +0900378 }
379
380 private boolean checkGatewayNode(DeviceId deviceId) {
Daniel Park81a61a12016-02-26 08:24:44 +0900381 return deviceId.toString().equals(config.gatewayBridgeId());
sangho0c2a3da2016-02-16 13:39:07 +0900382 }
383
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900384 private long getVni(String netId) {
385 return Long.parseLong(openstackService.network(netId).segmentId());
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900386 }
387
388 /**
389 * Remove flow rules for external connection.
390 *
391 * @param routerInterface Corresponding routerInterface
392 */
sangho0c2a3da2016-02-16 13:39:07 +0900393 public void removeExternalRules(OpenstackRouterInterface routerInterface) {
Kyuhwi Choie2b37e32016-02-05 14:04:14 +0900394 OpenstackSubnet openstackSubnet = openstackService.subnet(routerInterface.subnetId());
sangho0c2a3da2016-02-16 13:39:07 +0900395 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
396 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900397 .matchTunnelId(getVni(openstackSubnet.networkId()))
sangho0c2a3da2016-02-16 13:39:07 +0900398 .matchEthDst(GATEWAYMAC);
399
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900400 StreamSupport.stream(deviceService.getDevices().spliterator(), false)
sangho0c2a3da2016-02-16 13:39:07 +0900401 .forEach(d -> {
Daniel Park23193902016-03-24 18:17:19 +0900402 ForwardingObjective.Flag flag = checkGatewayNode(d.id()) ?
403 ForwardingObjective.Flag.VERSATILE : ForwardingObjective.Flag.SPECIFIC;
404
405 removeRule(d.id(), sBuilder, flag, ROUTING_RULE_PRIORITY);
sangho0c2a3da2016-02-16 13:39:07 +0900406 });
407
408 }
409
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900410 private void removeRule(DeviceId id, TrafficSelector.Builder sBuilder,
411 ForwardingObjective.Flag flag, int priority) {
sangho0c2a3da2016-02-16 13:39:07 +0900412 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
413
414 ForwardingObjective fo = DefaultForwardingObjective.builder()
415 .withSelector(sBuilder.build())
416 .withTreatment(tBuilder.build())
417 .withFlag(flag)
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900418 .withPriority(priority)
sangho0c2a3da2016-02-16 13:39:07 +0900419 .fromApp(appId)
420 .remove();
421
422 flowObjectiveService.forward(id, fo);
423 }
424
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900425 /**
426 * Populates flow rules for floatingIp configuration.
427 *
428 * @param floatingIP Corresponding floating ip information
429 */
430 public void populateFloatingIpRules(OpenstackFloatingIP floatingIP) {
431 OpenstackPort port = openstackService.port(floatingIP.portId());
432 //1. incoming rules
433 populateFloatingIpIncomingRules(floatingIP, port);
434 //2. outgoing rules
435 populateFloatingIpOutgoingRules(floatingIP, port);
436 }
437
438 private void populateFloatingIpIncomingRules(OpenstackFloatingIP floatingIP, OpenstackPort port) {
439 DeviceId portDeviceId = getDevicefromOpenstackPort(port).id();
440 Device gatewayNode = getGatewayNode();
441 Device portNode = deviceService.getDevice(portDeviceId);
442
443 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
444 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
445
446 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
Daniel Park23193902016-03-24 18:17:19 +0900447 .matchIPDst(IpPrefix.valueOf(floatingIP.floatingIpAddress(), PREFIX_LENGTH));
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900448
449 tBuilder.setEthSrc(MacAddress.valueOf(config.gatewayExternalInterfaceMac()))
450 .setEthDst(port.macAddress())
451 .setIpDst(floatingIP.fixedIpAddress())
452 .setTunnelId(getVni(port.networkId()))
Daniel Park23193902016-03-24 18:17:19 +0900453 .extension(buildNiciraExtenstion(gatewayNode.id(),
454 config.nodes().get(portNode.id())), gatewayNode.id())
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900455 .setOutput(getTunnelPort(gatewayNode.id()));
456
457 ForwardingObjective fo = DefaultForwardingObjective.builder()
458 .withSelector(sBuilder.build())
459 .withTreatment(tBuilder.build())
460 .withFlag(ForwardingObjective.Flag.VERSATILE)
461 .withPriority(FLOATING_RULE_PRIORITY)
462 .fromApp(appId)
463 .add();
464
465 flowObjectiveService.forward(getGatewayNode().id(), fo);
466
467 }
468
469 private void populateFloatingIpOutgoingRules(OpenstackFloatingIP floatingIP, OpenstackPort port) {
470 Port outputPort = checkNotNull(getPortOfExternalInterface(), PORTNOTNULL);
471
472 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
473 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
474
475 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
476 .matchTunnelId(getVni(port.networkId()))
477 .matchIPSrc(IpPrefix.valueOf(floatingIP.fixedIpAddress(), 32));
478
479 tBuilder.setIpSrc(floatingIP.floatingIpAddress())
480 .setEthSrc(MacAddress.valueOf(config.gatewayExternalInterfaceMac()))
481 .setEthDst(MacAddress.valueOf(config.physicalRouterMac()))
482 .setOutput(outputPort.number());
483
484 ForwardingObjective fo = DefaultForwardingObjective.builder()
485 .withSelector(sBuilder.build())
486 .withTreatment(tBuilder.build())
487 .withFlag(ForwardingObjective.Flag.VERSATILE)
488 .withPriority(FLOATING_RULE_PRIORITY)
489 .fromApp(appId)
490 .add();
491
492 flowObjectiveService.forward(getGatewayNode().id(), fo);
493 }
494
495 /**
496 * Removes flow rules for floating ip configuration.
497 *
498 * @param floatingIP Corresponding floating ip information
Ray Milkeyd4334db2016-04-05 17:39:44 -0700499 * @param portInfo stored information about deleted vm
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900500 */
501 public void removeFloatingIpRules(OpenstackFloatingIP floatingIP, OpenstackPortInfo portInfo) {
502 TrafficSelector.Builder sOutgoingBuilder = DefaultTrafficSelector.builder();
503 TrafficSelector.Builder sIncomingBuilder = DefaultTrafficSelector.builder();
504
505 sOutgoingBuilder.matchEthType(Ethernet.TYPE_IPV4)
506 .matchTunnelId(portInfo.vni())
Daniel Park23193902016-03-24 18:17:19 +0900507 .matchIPSrc(IpPrefix.valueOf(portInfo.ip(), PREFIX_LENGTH));
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900508
509 sIncomingBuilder.matchEthType(Ethernet.TYPE_IPV4)
Daniel Park23193902016-03-24 18:17:19 +0900510 .matchIPDst(IpPrefix.valueOf(floatingIP.floatingIpAddress(), PREFIX_LENGTH));
Kyuhwi Choiee9e3712016-02-22 22:49:36 +0900511
512 removeRule(getGatewayNode().id(), sOutgoingBuilder, ForwardingObjective.Flag.VERSATILE, FLOATING_RULE_PRIORITY);
513 removeRule(getGatewayNode().id(), sIncomingBuilder, ForwardingObjective.Flag.VERSATILE, FLOATING_RULE_PRIORITY);
514 }
515
sangho0c2a3da2016-02-16 13:39:07 +0900516}