blob: fdc39ad1c14aeb2776ba673628c4f2f0dbb00855 [file] [log] [blame]
Hyunsun Moon44aac662017-02-18 02:07:01 +09001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002* Copyright 2016-present Open Networking Foundation
Hyunsun Moon44aac662017-02-18 02:07:01 +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*/
16
17package org.onosproject.openstacknetworking.impl;
18
19import com.google.common.base.Strings;
20import org.apache.felix.scr.annotations.Activate;
21import org.apache.felix.scr.annotations.Component;
22import org.apache.felix.scr.annotations.Deactivate;
23import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
25import org.onlab.packet.Ethernet;
Frank Wangf9571662017-06-06 18:01:29 +080026import org.onlab.packet.MacAddress;
daniel parka792cf72017-04-14 16:25:35 +090027import org.onlab.packet.VlanId;
Hyunsun Moon44aac662017-02-18 02:07:01 +090028import org.onosproject.core.ApplicationId;
29import org.onosproject.core.CoreService;
30import org.onosproject.mastership.MastershipService;
daniel park796c2eb2018-03-22 17:01:51 +090031import org.onosproject.net.PortNumber;
Hyunsun Moon44aac662017-02-18 02:07:01 +090032import org.onosproject.net.device.DeviceService;
sangho1aaa7882017-05-31 13:22:47 +090033import org.onosproject.net.driver.DriverService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090034import org.onosproject.net.flow.DefaultTrafficSelector;
35import org.onosproject.net.flow.DefaultTrafficTreatment;
36import org.onosproject.net.flow.TrafficSelector;
37import org.onosproject.net.flow.TrafficTreatment;
sangho1aaa7882017-05-31 13:22:47 +090038import org.onosproject.net.flow.instructions.ExtensionTreatment;
Hyunsun Moon44aac662017-02-18 02:07:01 +090039import org.onosproject.openstacknetworking.api.InstancePort;
40import org.onosproject.openstacknetworking.api.InstancePortEvent;
41import org.onosproject.openstacknetworking.api.InstancePortListener;
42import org.onosproject.openstacknetworking.api.InstancePortService;
sanghodc375372017-06-08 10:41:30 +090043import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090044import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
sanghoe6457a32017-08-24 14:31:19 +090045import org.onosproject.openstacknetworking.api.OpenstackSecurityGroupService;
Hyunsun Moon0d457362017-06-27 17:19:41 +090046import org.onosproject.openstacknode.api.OpenstackNode;
47import org.onosproject.openstacknode.api.OpenstackNodeService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090048import org.openstack4j.model.network.Network;
Frank Wangf9571662017-06-06 18:01:29 +080049import org.openstack4j.model.network.NetworkType;
50import org.openstack4j.model.network.Port;
Hyunsun Moon44aac662017-02-18 02:07:01 +090051import org.slf4j.Logger;
52
53import java.util.concurrent.ExecutorService;
54
55import static java.util.concurrent.Executors.newSingleThreadExecutor;
56import static org.onlab.util.Tools.groupedThreads;
sanghodc375372017-06-08 10:41:30 +090057import static org.onosproject.openstacknetworking.api.Constants.ACL_TABLE;
58import static org.onosproject.openstacknetworking.api.Constants.FORWARDING_TABLE;
59import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
Frank Wangf9571662017-06-06 18:01:29 +080060import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ADMIN_RULE;
daniel park796c2eb2018-03-22 17:01:51 +090061import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FLAT_RULE;
sanghodc375372017-06-08 10:41:30 +090062import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_SWITCHING_RULE;
63import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_TUNNEL_TAG_RULE;
64import static org.onosproject.openstacknetworking.api.Constants.SRC_VNI_TABLE;
Hyunsun Moon44aac662017-02-18 02:07:01 +090065import static org.onosproject.openstacknetworking.impl.RulePopulatorUtil.buildExtension;
Hyunsun Moon0d457362017-06-27 17:19:41 +090066import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
Hyunsun Moon44aac662017-02-18 02:07:01 +090067import static org.slf4j.LoggerFactory.getLogger;
68
69
70/**
71 * Populates switching flow rules on OVS for the basic connectivity among the
72 * virtual instances in the same network.
73 */
74@Component(immediate = true)
75public final class OpenstackSwitchingHandler {
76
77 private final Logger log = getLogger(getClass());
78
Jian Li71670d12018-03-02 21:31:07 +090079 private static final String ERR_SET_FLOWS_VNI = "Failed to set flows for %s: Failed to get VNI for %s";
Hyunsun Moon44aac662017-02-18 02:07:01 +090080
81 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Liea1b9662018-03-02 18:07:32 +090082 protected CoreService coreService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090083
84 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Liea1b9662018-03-02 18:07:32 +090085 protected MastershipService mastershipService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090086
87 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Liea1b9662018-03-02 18:07:32 +090088 protected DeviceService deviceService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090089
90 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Liea1b9662018-03-02 18:07:32 +090091 protected OpenstackFlowRuleService osFlowRuleService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090092
93 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Liea1b9662018-03-02 18:07:32 +090094 protected InstancePortService instancePortService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090095
96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Liea1b9662018-03-02 18:07:32 +090097 protected OpenstackNetworkService osNetworkService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090098
99 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Liea1b9662018-03-02 18:07:32 +0900100 protected OpenstackNodeService osNodeService;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900101
sangho1aaa7882017-05-31 13:22:47 +0900102 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Liea1b9662018-03-02 18:07:32 +0900103 protected DriverService driverService;
sangho1aaa7882017-05-31 13:22:47 +0900104
sanghoe6457a32017-08-24 14:31:19 +0900105 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Liea1b9662018-03-02 18:07:32 +0900106 protected OpenstackSecurityGroupService securityGroupService;
sanghoe6457a32017-08-24 14:31:19 +0900107
Hyunsun Moon44aac662017-02-18 02:07:01 +0900108 private final ExecutorService eventExecutor = newSingleThreadExecutor(
109 groupedThreads(this.getClass().getSimpleName(), "event-handler"));
110 private final InstancePortListener instancePortListener = new InternalInstancePortListener();
111 private ApplicationId appId;
112
113 @Activate
Ray Milkey9c9cde42018-01-12 14:22:06 -0800114 void activate() {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900115 appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
116 instancePortService.addListener(instancePortListener);
117
118 log.info("Started");
119 }
120
121 @Deactivate
Ray Milkey9c9cde42018-01-12 14:22:06 -0800122 void deactivate() {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900123 instancePortService.removeListener(instancePortListener);
124 eventExecutor.shutdown();
125
126 log.info("Stopped");
127 }
128
Jian Liea1b9662018-03-02 18:07:32 +0900129 /**
130 * Configures L2 forwarding rules.
daniel park796c2eb2018-03-22 17:01:51 +0900131 * Currently, SONA supports Flat, VXLAN and VLAN modes.
Jian Liea1b9662018-03-02 18:07:32 +0900132 *
133 * @param instPort instance port object
134 * @param install install flag, add the rule if true, remove it otherwise
135 */
Hyunsun Moon44aac662017-02-18 02:07:01 +0900136 private void setNetworkRules(InstancePort instPort, boolean install) {
Jian Liea1b9662018-03-02 18:07:32 +0900137 NetworkType type = osNetworkService.network(instPort.networkId()).getNetworkType();
138 switch (type) {
daniel parka792cf72017-04-14 16:25:35 +0900139 case VXLAN:
140 setTunnelTagFlowRules(instPort, install);
141 setForwardingRules(instPort, install);
142 break;
143 case VLAN:
144 setVlanTagFlowRules(instPort, install);
145 setForwardingRulesForVlan(instPort, install);
146 break;
daniel park796c2eb2018-03-22 17:01:51 +0900147 case FLAT:
148 setDownstreamRules(instPort, install);
149 setUpstreamRules(instPort, install);
150 break;
daniel parka792cf72017-04-14 16:25:35 +0900151 default:
Jian Liea1b9662018-03-02 18:07:32 +0900152 log.warn("Unsupported network tunnel type {}", type.name());
daniel parka792cf72017-04-14 16:25:35 +0900153 break;
154 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900155 }
156
daniel park796c2eb2018-03-22 17:01:51 +0900157 private void setDownstreamRules(InstancePort instPort, boolean install) {
158 TrafficSelector selector = DefaultTrafficSelector.builder()
159 .matchEthType(Ethernet.TYPE_IPV4)
160 .matchIPDst(instPort.ipAddress().toIpPrefix())
161 .build();
162 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
163 .setOutput(instPort.portNumber())
164 .build();
165
166 osFlowRuleService.setRule(
167 appId,
168 instPort.deviceId(),
169 selector,
170 treatment,
171 PRIORITY_FLAT_RULE,
172 SRC_VNI_TABLE,
173 install);
174
175 selector = DefaultTrafficSelector.builder()
176 .matchEthType(Ethernet.TYPE_ARP)
177 .matchArpTpa(instPort.ipAddress().getIp4Address())
178 .build();
179
180 osFlowRuleService.setRule(
181 appId,
182 instPort.deviceId(),
183 selector,
184 treatment,
185 PRIORITY_FLAT_RULE,
186 SRC_VNI_TABLE,
187 install);
188 }
189
190 private void setUpstreamRules(InstancePort instPort, boolean install) {
191 TrafficSelector selector = DefaultTrafficSelector.builder()
192 .matchInPort(instPort.portNumber())
193 .build();
194
195 Network network = osNetworkService.network(instPort.networkId());
196
197 if (network == null) {
198 log.warn("The network does not exist");
199 return;
200 }
201
202 PortNumber portNumber = osNodeService.node(instPort.deviceId())
203 .phyIntfPortNum(network.getProviderPhyNet());
204
205 if (portNumber == null) {
206 log.warn("The port number does not exist");
207 return;
208 }
209
210 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
211 .setOutput(portNumber)
212 .build();
213
214 osFlowRuleService.setRule(
215 appId,
216 instPort.deviceId(),
217 selector,
218 treatment,
219 PRIORITY_FLAT_RULE,
220 SRC_VNI_TABLE,
221 install);
222 }
223
224
Jian Liea1b9662018-03-02 18:07:32 +0900225 /**
226 * Configures the flow rules which are used for L2 packet switching.
227 * Note that these rules will be inserted in switching table (table 5).
228 *
229 * @param instPort instance port object
230 * @param install install flag, add the rule if true, remove it otherwise
231 */
Hyunsun Moon44aac662017-02-18 02:07:01 +0900232 private void setForwardingRules(InstancePort instPort, boolean install) {
233 // switching rules for the instPorts in the same node
234 TrafficSelector selector = DefaultTrafficSelector.builder()
Jian Liea1b9662018-03-02 18:07:32 +0900235 // TODO: need to handle IPv6 in near future
Hyunsun Moon44aac662017-02-18 02:07:01 +0900236 .matchEthType(Ethernet.TYPE_IPV4)
237 .matchIPDst(instPort.ipAddress().toIpPrefix())
238 .matchTunnelId(getVni(instPort))
239 .build();
240
241 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Jian Liea1b9662018-03-02 18:07:32 +0900242 // TODO: this might not be necessary for the VMs located in the same subnet
Hyunsun Moon44aac662017-02-18 02:07:01 +0900243 .setEthDst(instPort.macAddress())
244 .setOutput(instPort.portNumber())
245 .build();
246
sanghodc375372017-06-08 10:41:30 +0900247 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900248 appId,
249 instPort.deviceId(),
250 selector,
251 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900252 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900253 FORWARDING_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900254 install);
255
256 // switching rules for the instPorts in the remote node
Hyunsun Moon0d457362017-06-27 17:19:41 +0900257 OpenstackNode localNode = osNodeService.node(instPort.deviceId());
258 if (localNode == null) {
259 final String error = String.format("Cannot find openstack node for %s",
260 instPort.deviceId());
261 throw new IllegalStateException(error);
262 }
263 osNodeService.completeNodes(COMPUTE).stream()
264 .filter(remoteNode -> !remoteNode.intgBridge().equals(localNode.intgBridge()))
265 .forEach(remoteNode -> {
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900266 TrafficTreatment treatmentToRemote = DefaultTrafficTreatment.builder()
267 .extension(buildExtension(
268 deviceService,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900269 remoteNode.intgBridge(),
270 localNode.dataIp().getIp4Address()),
271 remoteNode.intgBridge())
272 .setOutput(remoteNode.tunnelPortNum())
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900273 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900274
sanghodc375372017-06-08 10:41:30 +0900275 osFlowRuleService.setRule(
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900276 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900277 remoteNode.intgBridge(),
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900278 selector,
279 treatmentToRemote,
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900280 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900281 FORWARDING_TABLE,
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900282 install);
283 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900284 }
285
Jian Liea1b9662018-03-02 18:07:32 +0900286 /**
287 * Configures the flow rules which are used for L2 VLAN packet switching.
288 * Note that these rules will be inserted in switching table (table 5).
289 *
290 * @param instPort instance port object
291 * @param install install flag, add the rule if true, remove it otherwise
292 */
daniel parka792cf72017-04-14 16:25:35 +0900293 private void setForwardingRulesForVlan(InstancePort instPort, boolean install) {
294 // switching rules for the instPorts in the same node
295 TrafficSelector selector = DefaultTrafficSelector.builder()
Jian Liea1b9662018-03-02 18:07:32 +0900296 // TODO: need to handle IPv6 in near future
daniel parka792cf72017-04-14 16:25:35 +0900297 .matchEthType(Ethernet.TYPE_IPV4)
298 .matchIPDst(instPort.ipAddress().toIpPrefix())
299 .matchVlanId(getVlanId(instPort))
300 .build();
301
302 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
303 .popVlan()
Jian Liea1b9662018-03-02 18:07:32 +0900304 // TODO: this might not be necessary for the VMs located in the same subnet
daniel parka792cf72017-04-14 16:25:35 +0900305 .setEthDst(instPort.macAddress())
306 .setOutput(instPort.portNumber())
307 .build();
308
sanghodc375372017-06-08 10:41:30 +0900309 osFlowRuleService.setRule(
daniel parka792cf72017-04-14 16:25:35 +0900310 appId,
311 instPort.deviceId(),
312 selector,
313 treatment,
daniel parka792cf72017-04-14 16:25:35 +0900314 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900315 FORWARDING_TABLE,
daniel parka792cf72017-04-14 16:25:35 +0900316 install);
317
318 // switching rules for the instPorts in the remote node
Hyunsun Moon0d457362017-06-27 17:19:41 +0900319 osNodeService.completeNodes(COMPUTE).stream()
320 .filter(remoteNode -> !remoteNode.intgBridge().equals(instPort.deviceId()) &&
321 remoteNode.vlanIntf() != null)
322 .forEach(remoteNode -> {
daniel parka792cf72017-04-14 16:25:35 +0900323 TrafficTreatment treatmentToRemote = DefaultTrafficTreatment.builder()
Hyunsun Moon0d457362017-06-27 17:19:41 +0900324 .setOutput(remoteNode.vlanPortNum())
daniel parka792cf72017-04-14 16:25:35 +0900325 .build();
326
sanghodc375372017-06-08 10:41:30 +0900327 osFlowRuleService.setRule(
daniel parka792cf72017-04-14 16:25:35 +0900328 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900329 remoteNode.intgBridge(),
daniel parka792cf72017-04-14 16:25:35 +0900330 selector,
331 treatmentToRemote,
daniel parka792cf72017-04-14 16:25:35 +0900332 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900333 FORWARDING_TABLE,
daniel parka792cf72017-04-14 16:25:35 +0900334 install);
335 });
daniel parka792cf72017-04-14 16:25:35 +0900336 }
337
Jian Liea1b9662018-03-02 18:07:32 +0900338 /**
339 * Configures the flow rule which is for using VXLAN to tag the packet
340 * based on the in_port number of a virtual instance.
341 * Note that this rule will be inserted in VNI table (table 0).
342 *
343 * @param instPort instance port object
344 * @param install install flag, add the rule if true, remove it otherwise
345 */
Hyunsun Moon44aac662017-02-18 02:07:01 +0900346 private void setTunnelTagFlowRules(InstancePort instPort, boolean install) {
347 TrafficSelector selector = DefaultTrafficSelector.builder()
Jian Liea1b9662018-03-02 18:07:32 +0900348 // TODO: need to handle IPv6 in near future
Hyunsun Moon44aac662017-02-18 02:07:01 +0900349 .matchEthType(Ethernet.TYPE_IPV4)
350 .matchInPort(instPort.portNumber())
351 .build();
352
Jian Liea1b9662018-03-02 18:07:32 +0900353 // XXX All egress traffic needs to go through connection tracking module,
354 // which might hurt its performance.
sangho1aaa7882017-05-31 13:22:47 +0900355 ExtensionTreatment ctTreatment =
356 RulePopulatorUtil.niciraConnTrackTreatmentBuilder(driverService, instPort.deviceId())
357 .commit(true).build();
358
sanghoe6457a32017-08-24 14:31:19 +0900359 TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900360 .setTunnelId(getVni(instPort))
sanghoe6457a32017-08-24 14:31:19 +0900361 .transition(ACL_TABLE);
362
363 if (securityGroupService.isSecurityGroupEnabled()) {
364 tb.extension(ctTreatment, instPort.deviceId());
365 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900366
sanghodc375372017-06-08 10:41:30 +0900367 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900368 appId,
369 instPort.deviceId(),
370 selector,
sanghoe6457a32017-08-24 14:31:19 +0900371 tb.build(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900372 PRIORITY_TUNNEL_TAG_RULE,
sanghodc375372017-06-08 10:41:30 +0900373 SRC_VNI_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900374 install);
375 }
376
Jian Liea1b9662018-03-02 18:07:32 +0900377 /**
378 * Configures the flow rule which is for using VLAN to tag the packet
379 * based on the in_port number of a virtual instance.
380 * Note that this rule will be inserted in VNI table (table 0).
381 *
382 * @param instPort instance port object
383 * @param install install flag, add the rule if true, remove it otherwise
384 */
daniel parka792cf72017-04-14 16:25:35 +0900385 private void setVlanTagFlowRules(InstancePort instPort, boolean install) {
386 TrafficSelector selector = DefaultTrafficSelector.builder()
Jian Liea1b9662018-03-02 18:07:32 +0900387 // TODO: need to handle IPv6 in near future
daniel parka792cf72017-04-14 16:25:35 +0900388 .matchEthType(Ethernet.TYPE_IPV4)
389 .matchInPort(instPort.portNumber())
390 .build();
391
392 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
393 .pushVlan()
394 .setVlanId(getVlanId(instPort))
sanghodc375372017-06-08 10:41:30 +0900395 .transition(ACL_TABLE)
daniel parka792cf72017-04-14 16:25:35 +0900396 .build();
397
sanghodc375372017-06-08 10:41:30 +0900398 osFlowRuleService.setRule(
daniel parka792cf72017-04-14 16:25:35 +0900399 appId,
400 instPort.deviceId(),
401 selector,
402 treatment,
daniel parka792cf72017-04-14 16:25:35 +0900403 PRIORITY_TUNNEL_TAG_RULE,
sanghodc375372017-06-08 10:41:30 +0900404 SRC_VNI_TABLE,
daniel parka792cf72017-04-14 16:25:35 +0900405 install);
daniel parka792cf72017-04-14 16:25:35 +0900406 }
407
Frank Wangf9571662017-06-06 18:01:29 +0800408 private void setNetworkAdminRules(Network network, boolean install) {
409 TrafficSelector selector;
410 if (network.getNetworkType() == NetworkType.VXLAN) {
411
412 selector = DefaultTrafficSelector.builder()
413 .matchTunnelId(Long.valueOf(network.getProviderSegID()))
414 .build();
415 } else {
416 selector = DefaultTrafficSelector.builder()
417 .matchVlanId(VlanId.vlanId(network.getProviderSegID()))
418 .build();
419 }
420
421 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
422 .drop()
423 .build();
424
425 osNodeService.completeNodes().stream()
426 .filter(osNode -> osNode.type() == COMPUTE)
Jian Liea1b9662018-03-02 18:07:32 +0900427 .forEach(osNode ->
Frank Wangf9571662017-06-06 18:01:29 +0800428 osFlowRuleService.setRule(
429 appId,
430 osNode.intgBridge(),
431 selector,
432 treatment,
433 PRIORITY_ADMIN_RULE,
434 ACL_TABLE,
Jian Liea1b9662018-03-02 18:07:32 +0900435 install)
436 );
Frank Wangf9571662017-06-06 18:01:29 +0800437 }
438
439 private void setPortAdminRules(Port port, boolean install) {
Jian Liea1b9662018-03-02 18:07:32 +0900440 InstancePort instancePort =
441 instancePortService.instancePort(MacAddress.valueOf(port.getMacAddress()));
Frank Wangf9571662017-06-06 18:01:29 +0800442 TrafficSelector selector = DefaultTrafficSelector.builder()
443 .matchInPort(instancePort.portNumber())
444 .build();
445
446 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
447 .drop()
448 .build();
449
450 osFlowRuleService.setRule(
451 appId,
452 instancePort.deviceId(),
453 selector,
454 treatment,
455 PRIORITY_ADMIN_RULE,
456 SRC_VNI_TABLE,
457 install);
458 }
459
Jian Liea1b9662018-03-02 18:07:32 +0900460 /**
461 * Obtains the VLAN ID from the given instance port.
462 *
463 * @param instPort instance port object
464 * @return VLAN ID
465 */
daniel parka792cf72017-04-14 16:25:35 +0900466 private VlanId getVlanId(InstancePort instPort) {
467 Network osNet = osNetworkService.network(instPort.networkId());
468
469 if (osNet == null || Strings.isNullOrEmpty(osNet.getProviderSegID())) {
Jian Li71670d12018-03-02 21:31:07 +0900470 final String error =
471 String.format(ERR_SET_FLOWS_VNI,
472 instPort, osNet == null ? "<none>" : osNet.getName());
daniel parka792cf72017-04-14 16:25:35 +0900473 throw new IllegalStateException(error);
474 }
475
476 return VlanId.vlanId(osNet.getProviderSegID());
477 }
478
Jian Liea1b9662018-03-02 18:07:32 +0900479 /**
480 * Obtains the VNI from the given instance port.
481 *
482 * @param instPort instance port object
483 * @return VXLAN Network Identifier (VNI)
484 */
Hyunsun Moon44aac662017-02-18 02:07:01 +0900485 private Long getVni(InstancePort instPort) {
486 Network osNet = osNetworkService.network(instPort.networkId());
487 if (osNet == null || Strings.isNullOrEmpty(osNet.getProviderSegID())) {
Jian Li71670d12018-03-02 21:31:07 +0900488 final String error =
489 String.format(ERR_SET_FLOWS_VNI,
490 instPort, osNet == null ? "<none>" : osNet.getName());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900491 throw new IllegalStateException(error);
492 }
493 return Long.valueOf(osNet.getProviderSegID());
494 }
495
Jian Liea1b9662018-03-02 18:07:32 +0900496 /**
497 * An internal instance port listener which listens the port events generated
498 * from VM. The corresponding L2 forwarding rules will be generated and
499 * inserted to integration bridge only if a new VM port is detected. If the
500 * existing detected VM port is removed due to VM purge, we will remove the
501 * corresponding L2 forwarding to as well for the sake of resource saving.
502 */
Hyunsun Moon44aac662017-02-18 02:07:01 +0900503 private class InternalInstancePortListener implements InstancePortListener {
504
505 @Override
506 public boolean isRelevant(InstancePortEvent event) {
507 InstancePort instPort = event.subject();
508 return mastershipService.isLocalMaster(instPort.deviceId());
509 }
510
511 @Override
512 public void event(InstancePortEvent event) {
513 InstancePort instPort = event.subject();
514 switch (event.type()) {
515 case OPENSTACK_INSTANCE_PORT_UPDATED:
516 case OPENSTACK_INSTANCE_PORT_DETECTED:
517 eventExecutor.execute(() -> {
518 log.info("Instance port detected MAC:{} IP:{}",
519 instPort.macAddress(),
520 instPort.ipAddress());
521 instPortDetected(event.subject());
522 });
523 break;
524 case OPENSTACK_INSTANCE_PORT_VANISHED:
525 eventExecutor.execute(() -> {
526 log.info("Instance port vanished MAC:{} IP:{}",
527 instPort.macAddress(),
528 instPort.ipAddress());
529 instPortRemoved(event.subject());
530 });
531 break;
532 default:
533 break;
534 }
535 }
536
537 private void instPortDetected(InstancePort instPort) {
538 setNetworkRules(instPort, true);
539 // TODO add something else if needed
540 }
541
542 private void instPortRemoved(InstancePort instPort) {
543 setNetworkRules(instPort, false);
544 // TODO add something else if needed
545 }
546 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900547}