blob: 38481749de1d61f541e16fc166f42ce9949f5e7f [file] [log] [blame]
Hyunsun Moon44aac662017-02-18 02:07:01 +09001/*
Jian Li26949762018-03-30 15:46:37 +09002 * Copyright 2016-present Open Networking Foundation
3 *
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 Moon44aac662017-02-18 02:07:01 +090016
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;
Jian Li26949762018-03-30 15:46:37 +090046import org.onosproject.openstacknetworking.util.RulePopulatorUtil;
Hyunsun Moon0d457362017-06-27 17:19:41 +090047import org.onosproject.openstacknode.api.OpenstackNode;
48import org.onosproject.openstacknode.api.OpenstackNodeService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090049import org.openstack4j.model.network.Network;
Frank Wangf9571662017-06-06 18:01:29 +080050import org.openstack4j.model.network.NetworkType;
51import org.openstack4j.model.network.Port;
Hyunsun Moon44aac662017-02-18 02:07:01 +090052import org.slf4j.Logger;
53
54import java.util.concurrent.ExecutorService;
55
56import static java.util.concurrent.Executors.newSingleThreadExecutor;
57import static org.onlab.util.Tools.groupedThreads;
sanghodc375372017-06-08 10:41:30 +090058import static org.onosproject.openstacknetworking.api.Constants.ACL_TABLE;
59import static org.onosproject.openstacknetworking.api.Constants.FORWARDING_TABLE;
60import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
Frank Wangf9571662017-06-06 18:01:29 +080061import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ADMIN_RULE;
daniel park796c2eb2018-03-22 17:01:51 +090062import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FLAT_RULE;
sanghodc375372017-06-08 10:41:30 +090063import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_SWITCHING_RULE;
64import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_TUNNEL_TAG_RULE;
65import static org.onosproject.openstacknetworking.api.Constants.SRC_VNI_TABLE;
Jian Li26949762018-03-30 15:46:37 +090066import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension;
Hyunsun Moon0d457362017-06-27 17:19:41 +090067import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
Hyunsun Moon44aac662017-02-18 02:07:01 +090068import static org.slf4j.LoggerFactory.getLogger;
69
70
71/**
72 * Populates switching flow rules on OVS for the basic connectivity among the
73 * virtual instances in the same network.
74 */
75@Component(immediate = true)
76public final class OpenstackSwitchingHandler {
77
78 private final Logger log = getLogger(getClass());
79
Jian Li71670d12018-03-02 21:31:07 +090080 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 +090081
82 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Liea1b9662018-03-02 18:07:32 +090083 protected CoreService coreService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090084
85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Liea1b9662018-03-02 18:07:32 +090086 protected MastershipService mastershipService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090087
88 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Liea1b9662018-03-02 18:07:32 +090089 protected DeviceService deviceService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090090
91 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Liea1b9662018-03-02 18:07:32 +090092 protected OpenstackFlowRuleService osFlowRuleService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090093
94 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Liea1b9662018-03-02 18:07:32 +090095 protected InstancePortService instancePortService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090096
97 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Liea1b9662018-03-02 18:07:32 +090098 protected OpenstackNetworkService osNetworkService;
Hyunsun Moon44aac662017-02-18 02:07:01 +090099
100 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Liea1b9662018-03-02 18:07:32 +0900101 protected OpenstackNodeService osNodeService;
Hyunsun Moon44aac662017-02-18 02:07:01 +0900102
sangho1aaa7882017-05-31 13:22:47 +0900103 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Liea1b9662018-03-02 18:07:32 +0900104 protected DriverService driverService;
sangho1aaa7882017-05-31 13:22:47 +0900105
sanghoe6457a32017-08-24 14:31:19 +0900106 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Jian Liea1b9662018-03-02 18:07:32 +0900107 protected OpenstackSecurityGroupService securityGroupService;
sanghoe6457a32017-08-24 14:31:19 +0900108
Hyunsun Moon44aac662017-02-18 02:07:01 +0900109 private final ExecutorService eventExecutor = newSingleThreadExecutor(
110 groupedThreads(this.getClass().getSimpleName(), "event-handler"));
111 private final InstancePortListener instancePortListener = new InternalInstancePortListener();
112 private ApplicationId appId;
113
114 @Activate
Ray Milkey9c9cde42018-01-12 14:22:06 -0800115 void activate() {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900116 appId = coreService.registerApplication(OPENSTACK_NETWORKING_APP_ID);
117 instancePortService.addListener(instancePortListener);
118
119 log.info("Started");
120 }
121
122 @Deactivate
Ray Milkey9c9cde42018-01-12 14:22:06 -0800123 void deactivate() {
Hyunsun Moon44aac662017-02-18 02:07:01 +0900124 instancePortService.removeListener(instancePortListener);
125 eventExecutor.shutdown();
126
127 log.info("Stopped");
128 }
129
Jian Liea1b9662018-03-02 18:07:32 +0900130 /**
131 * Configures L2 forwarding rules.
daniel park796c2eb2018-03-22 17:01:51 +0900132 * Currently, SONA supports Flat, VXLAN and VLAN modes.
Jian Liea1b9662018-03-02 18:07:32 +0900133 *
134 * @param instPort instance port object
135 * @param install install flag, add the rule if true, remove it otherwise
136 */
Hyunsun Moon44aac662017-02-18 02:07:01 +0900137 private void setNetworkRules(InstancePort instPort, boolean install) {
Jian Liea1b9662018-03-02 18:07:32 +0900138 NetworkType type = osNetworkService.network(instPort.networkId()).getNetworkType();
139 switch (type) {
daniel parka792cf72017-04-14 16:25:35 +0900140 case VXLAN:
141 setTunnelTagFlowRules(instPort, install);
142 setForwardingRules(instPort, install);
143 break;
144 case VLAN:
145 setVlanTagFlowRules(instPort, install);
146 setForwardingRulesForVlan(instPort, install);
147 break;
daniel park796c2eb2018-03-22 17:01:51 +0900148 case FLAT:
149 setDownstreamRules(instPort, install);
150 setUpstreamRules(instPort, install);
151 break;
daniel parka792cf72017-04-14 16:25:35 +0900152 default:
Jian Liea1b9662018-03-02 18:07:32 +0900153 log.warn("Unsupported network tunnel type {}", type.name());
daniel parka792cf72017-04-14 16:25:35 +0900154 break;
155 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900156 }
157
daniel park796c2eb2018-03-22 17:01:51 +0900158 private void setDownstreamRules(InstancePort instPort, boolean install) {
159 TrafficSelector selector = DefaultTrafficSelector.builder()
160 .matchEthType(Ethernet.TYPE_IPV4)
161 .matchIPDst(instPort.ipAddress().toIpPrefix())
162 .build();
163 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
164 .setOutput(instPort.portNumber())
165 .build();
166
167 osFlowRuleService.setRule(
168 appId,
169 instPort.deviceId(),
170 selector,
171 treatment,
172 PRIORITY_FLAT_RULE,
173 SRC_VNI_TABLE,
174 install);
175
176 selector = DefaultTrafficSelector.builder()
177 .matchEthType(Ethernet.TYPE_ARP)
178 .matchArpTpa(instPort.ipAddress().getIp4Address())
179 .build();
180
181 osFlowRuleService.setRule(
182 appId,
183 instPort.deviceId(),
184 selector,
185 treatment,
186 PRIORITY_FLAT_RULE,
187 SRC_VNI_TABLE,
188 install);
189 }
190
191 private void setUpstreamRules(InstancePort instPort, boolean install) {
192 TrafficSelector selector = DefaultTrafficSelector.builder()
193 .matchInPort(instPort.portNumber())
194 .build();
195
196 Network network = osNetworkService.network(instPort.networkId());
197
198 if (network == null) {
199 log.warn("The network does not exist");
200 return;
201 }
202
203 PortNumber portNumber = osNodeService.node(instPort.deviceId())
204 .phyIntfPortNum(network.getProviderPhyNet());
205
206 if (portNumber == null) {
207 log.warn("The port number does not exist");
208 return;
209 }
210
211 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
212 .setOutput(portNumber)
213 .build();
214
215 osFlowRuleService.setRule(
216 appId,
217 instPort.deviceId(),
218 selector,
219 treatment,
220 PRIORITY_FLAT_RULE,
221 SRC_VNI_TABLE,
222 install);
223 }
224
225
Jian Liea1b9662018-03-02 18:07:32 +0900226 /**
227 * Configures the flow rules which are used for L2 packet switching.
228 * Note that these rules will be inserted in switching table (table 5).
229 *
230 * @param instPort instance port object
231 * @param install install flag, add the rule if true, remove it otherwise
232 */
Hyunsun Moon44aac662017-02-18 02:07:01 +0900233 private void setForwardingRules(InstancePort instPort, boolean install) {
234 // switching rules for the instPorts in the same node
235 TrafficSelector selector = DefaultTrafficSelector.builder()
Jian Liea1b9662018-03-02 18:07:32 +0900236 // TODO: need to handle IPv6 in near future
Hyunsun Moon44aac662017-02-18 02:07:01 +0900237 .matchEthType(Ethernet.TYPE_IPV4)
238 .matchIPDst(instPort.ipAddress().toIpPrefix())
239 .matchTunnelId(getVni(instPort))
240 .build();
241
242 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
Jian Liea1b9662018-03-02 18:07:32 +0900243 // TODO: this might not be necessary for the VMs located in the same subnet
Hyunsun Moon44aac662017-02-18 02:07:01 +0900244 .setEthDst(instPort.macAddress())
245 .setOutput(instPort.portNumber())
246 .build();
247
sanghodc375372017-06-08 10:41:30 +0900248 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900249 appId,
250 instPort.deviceId(),
251 selector,
252 treatment,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900253 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900254 FORWARDING_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900255 install);
256
257 // switching rules for the instPorts in the remote node
Hyunsun Moon0d457362017-06-27 17:19:41 +0900258 OpenstackNode localNode = osNodeService.node(instPort.deviceId());
259 if (localNode == null) {
260 final String error = String.format("Cannot find openstack node for %s",
261 instPort.deviceId());
262 throw new IllegalStateException(error);
263 }
264 osNodeService.completeNodes(COMPUTE).stream()
265 .filter(remoteNode -> !remoteNode.intgBridge().equals(localNode.intgBridge()))
266 .forEach(remoteNode -> {
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900267 TrafficTreatment treatmentToRemote = DefaultTrafficTreatment.builder()
268 .extension(buildExtension(
269 deviceService,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900270 remoteNode.intgBridge(),
271 localNode.dataIp().getIp4Address()),
272 remoteNode.intgBridge())
273 .setOutput(remoteNode.tunnelPortNum())
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900274 .build();
Hyunsun Moon44aac662017-02-18 02:07:01 +0900275
sanghodc375372017-06-08 10:41:30 +0900276 osFlowRuleService.setRule(
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900277 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900278 remoteNode.intgBridge(),
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900279 selector,
280 treatmentToRemote,
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900281 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900282 FORWARDING_TABLE,
Hyunsun Moonacde3f52017-02-23 17:57:35 +0900283 install);
284 });
Hyunsun Moon44aac662017-02-18 02:07:01 +0900285 }
286
Jian Liea1b9662018-03-02 18:07:32 +0900287 /**
288 * Configures the flow rules which are used for L2 VLAN packet switching.
289 * Note that these rules will be inserted in switching table (table 5).
290 *
291 * @param instPort instance port object
292 * @param install install flag, add the rule if true, remove it otherwise
293 */
daniel parka792cf72017-04-14 16:25:35 +0900294 private void setForwardingRulesForVlan(InstancePort instPort, boolean install) {
295 // switching rules for the instPorts in the same node
296 TrafficSelector selector = DefaultTrafficSelector.builder()
Jian Liea1b9662018-03-02 18:07:32 +0900297 // TODO: need to handle IPv6 in near future
daniel parka792cf72017-04-14 16:25:35 +0900298 .matchEthType(Ethernet.TYPE_IPV4)
299 .matchIPDst(instPort.ipAddress().toIpPrefix())
300 .matchVlanId(getVlanId(instPort))
301 .build();
302
303 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
304 .popVlan()
Jian Liea1b9662018-03-02 18:07:32 +0900305 // TODO: this might not be necessary for the VMs located in the same subnet
daniel parka792cf72017-04-14 16:25:35 +0900306 .setEthDst(instPort.macAddress())
307 .setOutput(instPort.portNumber())
308 .build();
309
sanghodc375372017-06-08 10:41:30 +0900310 osFlowRuleService.setRule(
daniel parka792cf72017-04-14 16:25:35 +0900311 appId,
312 instPort.deviceId(),
313 selector,
314 treatment,
daniel parka792cf72017-04-14 16:25:35 +0900315 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900316 FORWARDING_TABLE,
daniel parka792cf72017-04-14 16:25:35 +0900317 install);
318
319 // switching rules for the instPorts in the remote node
Hyunsun Moon0d457362017-06-27 17:19:41 +0900320 osNodeService.completeNodes(COMPUTE).stream()
321 .filter(remoteNode -> !remoteNode.intgBridge().equals(instPort.deviceId()) &&
322 remoteNode.vlanIntf() != null)
323 .forEach(remoteNode -> {
daniel parka792cf72017-04-14 16:25:35 +0900324 TrafficTreatment treatmentToRemote = DefaultTrafficTreatment.builder()
Hyunsun Moon0d457362017-06-27 17:19:41 +0900325 .setOutput(remoteNode.vlanPortNum())
daniel parka792cf72017-04-14 16:25:35 +0900326 .build();
327
sanghodc375372017-06-08 10:41:30 +0900328 osFlowRuleService.setRule(
daniel parka792cf72017-04-14 16:25:35 +0900329 appId,
Hyunsun Moon0d457362017-06-27 17:19:41 +0900330 remoteNode.intgBridge(),
daniel parka792cf72017-04-14 16:25:35 +0900331 selector,
332 treatmentToRemote,
daniel parka792cf72017-04-14 16:25:35 +0900333 PRIORITY_SWITCHING_RULE,
sanghodc375372017-06-08 10:41:30 +0900334 FORWARDING_TABLE,
daniel parka792cf72017-04-14 16:25:35 +0900335 install);
336 });
daniel parka792cf72017-04-14 16:25:35 +0900337 }
338
Jian Liea1b9662018-03-02 18:07:32 +0900339 /**
340 * Configures the flow rule which is for using VXLAN to tag the packet
341 * based on the in_port number of a virtual instance.
342 * Note that this rule will be inserted in VNI table (table 0).
343 *
344 * @param instPort instance port object
345 * @param install install flag, add the rule if true, remove it otherwise
346 */
Hyunsun Moon44aac662017-02-18 02:07:01 +0900347 private void setTunnelTagFlowRules(InstancePort instPort, boolean install) {
348 TrafficSelector selector = DefaultTrafficSelector.builder()
Jian Liea1b9662018-03-02 18:07:32 +0900349 // TODO: need to handle IPv6 in near future
Hyunsun Moon44aac662017-02-18 02:07:01 +0900350 .matchEthType(Ethernet.TYPE_IPV4)
351 .matchInPort(instPort.portNumber())
352 .build();
353
Jian Liea1b9662018-03-02 18:07:32 +0900354 // XXX All egress traffic needs to go through connection tracking module,
355 // which might hurt its performance.
sangho1aaa7882017-05-31 13:22:47 +0900356 ExtensionTreatment ctTreatment =
357 RulePopulatorUtil.niciraConnTrackTreatmentBuilder(driverService, instPort.deviceId())
358 .commit(true).build();
359
sanghoe6457a32017-08-24 14:31:19 +0900360 TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder()
Hyunsun Moon44aac662017-02-18 02:07:01 +0900361 .setTunnelId(getVni(instPort))
sanghoe6457a32017-08-24 14:31:19 +0900362 .transition(ACL_TABLE);
363
364 if (securityGroupService.isSecurityGroupEnabled()) {
365 tb.extension(ctTreatment, instPort.deviceId());
366 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900367
sanghodc375372017-06-08 10:41:30 +0900368 osFlowRuleService.setRule(
Hyunsun Moon44aac662017-02-18 02:07:01 +0900369 appId,
370 instPort.deviceId(),
371 selector,
sanghoe6457a32017-08-24 14:31:19 +0900372 tb.build(),
Hyunsun Moon44aac662017-02-18 02:07:01 +0900373 PRIORITY_TUNNEL_TAG_RULE,
sanghodc375372017-06-08 10:41:30 +0900374 SRC_VNI_TABLE,
Hyunsun Moon44aac662017-02-18 02:07:01 +0900375 install);
376 }
377
Jian Liea1b9662018-03-02 18:07:32 +0900378 /**
379 * Configures the flow rule which is for using VLAN to tag the packet
380 * based on the in_port number of a virtual instance.
381 * Note that this rule will be inserted in VNI table (table 0).
382 *
383 * @param instPort instance port object
384 * @param install install flag, add the rule if true, remove it otherwise
385 */
daniel parka792cf72017-04-14 16:25:35 +0900386 private void setVlanTagFlowRules(InstancePort instPort, boolean install) {
387 TrafficSelector selector = DefaultTrafficSelector.builder()
Jian Liea1b9662018-03-02 18:07:32 +0900388 // TODO: need to handle IPv6 in near future
daniel parka792cf72017-04-14 16:25:35 +0900389 .matchEthType(Ethernet.TYPE_IPV4)
390 .matchInPort(instPort.portNumber())
391 .build();
392
393 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
394 .pushVlan()
395 .setVlanId(getVlanId(instPort))
sanghodc375372017-06-08 10:41:30 +0900396 .transition(ACL_TABLE)
daniel parka792cf72017-04-14 16:25:35 +0900397 .build();
398
sanghodc375372017-06-08 10:41:30 +0900399 osFlowRuleService.setRule(
daniel parka792cf72017-04-14 16:25:35 +0900400 appId,
401 instPort.deviceId(),
402 selector,
403 treatment,
daniel parka792cf72017-04-14 16:25:35 +0900404 PRIORITY_TUNNEL_TAG_RULE,
sanghodc375372017-06-08 10:41:30 +0900405 SRC_VNI_TABLE,
daniel parka792cf72017-04-14 16:25:35 +0900406 install);
daniel parka792cf72017-04-14 16:25:35 +0900407 }
408
Frank Wangf9571662017-06-06 18:01:29 +0800409 private void setNetworkAdminRules(Network network, boolean install) {
410 TrafficSelector selector;
411 if (network.getNetworkType() == NetworkType.VXLAN) {
412
413 selector = DefaultTrafficSelector.builder()
414 .matchTunnelId(Long.valueOf(network.getProviderSegID()))
415 .build();
416 } else {
417 selector = DefaultTrafficSelector.builder()
418 .matchVlanId(VlanId.vlanId(network.getProviderSegID()))
419 .build();
420 }
421
422 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
423 .drop()
424 .build();
425
426 osNodeService.completeNodes().stream()
427 .filter(osNode -> osNode.type() == COMPUTE)
Jian Liea1b9662018-03-02 18:07:32 +0900428 .forEach(osNode ->
Frank Wangf9571662017-06-06 18:01:29 +0800429 osFlowRuleService.setRule(
430 appId,
431 osNode.intgBridge(),
432 selector,
433 treatment,
434 PRIORITY_ADMIN_RULE,
435 ACL_TABLE,
Jian Liea1b9662018-03-02 18:07:32 +0900436 install)
437 );
Frank Wangf9571662017-06-06 18:01:29 +0800438 }
439
440 private void setPortAdminRules(Port port, boolean install) {
Jian Liea1b9662018-03-02 18:07:32 +0900441 InstancePort instancePort =
442 instancePortService.instancePort(MacAddress.valueOf(port.getMacAddress()));
Frank Wangf9571662017-06-06 18:01:29 +0800443 TrafficSelector selector = DefaultTrafficSelector.builder()
444 .matchInPort(instancePort.portNumber())
445 .build();
446
447 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
448 .drop()
449 .build();
450
451 osFlowRuleService.setRule(
452 appId,
453 instancePort.deviceId(),
454 selector,
455 treatment,
456 PRIORITY_ADMIN_RULE,
457 SRC_VNI_TABLE,
458 install);
459 }
460
Jian Liea1b9662018-03-02 18:07:32 +0900461 /**
462 * Obtains the VLAN ID from the given instance port.
463 *
464 * @param instPort instance port object
465 * @return VLAN ID
466 */
daniel parka792cf72017-04-14 16:25:35 +0900467 private VlanId getVlanId(InstancePort instPort) {
468 Network osNet = osNetworkService.network(instPort.networkId());
469
470 if (osNet == null || Strings.isNullOrEmpty(osNet.getProviderSegID())) {
Jian Li71670d12018-03-02 21:31:07 +0900471 final String error =
472 String.format(ERR_SET_FLOWS_VNI,
473 instPort, osNet == null ? "<none>" : osNet.getName());
daniel parka792cf72017-04-14 16:25:35 +0900474 throw new IllegalStateException(error);
475 }
476
477 return VlanId.vlanId(osNet.getProviderSegID());
478 }
479
Jian Liea1b9662018-03-02 18:07:32 +0900480 /**
481 * Obtains the VNI from the given instance port.
482 *
483 * @param instPort instance port object
484 * @return VXLAN Network Identifier (VNI)
485 */
Hyunsun Moon44aac662017-02-18 02:07:01 +0900486 private Long getVni(InstancePort instPort) {
487 Network osNet = osNetworkService.network(instPort.networkId());
488 if (osNet == null || Strings.isNullOrEmpty(osNet.getProviderSegID())) {
Jian Li71670d12018-03-02 21:31:07 +0900489 final String error =
490 String.format(ERR_SET_FLOWS_VNI,
491 instPort, osNet == null ? "<none>" : osNet.getName());
Hyunsun Moon44aac662017-02-18 02:07:01 +0900492 throw new IllegalStateException(error);
493 }
494 return Long.valueOf(osNet.getProviderSegID());
495 }
496
Jian Liea1b9662018-03-02 18:07:32 +0900497 /**
498 * An internal instance port listener which listens the port events generated
499 * from VM. The corresponding L2 forwarding rules will be generated and
500 * inserted to integration bridge only if a new VM port is detected. If the
501 * existing detected VM port is removed due to VM purge, we will remove the
502 * corresponding L2 forwarding to as well for the sake of resource saving.
503 */
Hyunsun Moon44aac662017-02-18 02:07:01 +0900504 private class InternalInstancePortListener implements InstancePortListener {
505
506 @Override
507 public boolean isRelevant(InstancePortEvent event) {
508 InstancePort instPort = event.subject();
509 return mastershipService.isLocalMaster(instPort.deviceId());
510 }
511
512 @Override
513 public void event(InstancePortEvent event) {
514 InstancePort instPort = event.subject();
515 switch (event.type()) {
516 case OPENSTACK_INSTANCE_PORT_UPDATED:
517 case OPENSTACK_INSTANCE_PORT_DETECTED:
518 eventExecutor.execute(() -> {
519 log.info("Instance port detected MAC:{} IP:{}",
520 instPort.macAddress(),
521 instPort.ipAddress());
522 instPortDetected(event.subject());
523 });
524 break;
525 case OPENSTACK_INSTANCE_PORT_VANISHED:
526 eventExecutor.execute(() -> {
527 log.info("Instance port vanished MAC:{} IP:{}",
528 instPort.macAddress(),
529 instPort.ipAddress());
530 instPortRemoved(event.subject());
531 });
532 break;
533 default:
534 break;
535 }
536 }
537
538 private void instPortDetected(InstancePort instPort) {
539 setNetworkRules(instPort, true);
540 // TODO add something else if needed
541 }
542
543 private void instPortRemoved(InstancePort instPort) {
544 setNetworkRules(instPort, false);
545 // TODO add something else if needed
546 }
547 }
Hyunsun Moon44aac662017-02-18 02:07:01 +0900548}