blob: 5b6aabf36c765a33f0adef679075d00acf3d0409 [file] [log] [blame]
Hyunsun Moonb974fca2016-06-30 21:20:39 -07001/*
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -07002* Copyright 2016-present Open Networking Laboratory
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*/
16
Hyunsun Moonb974fca2016-06-30 21:20:39 -070017package org.onosproject.openstacknetworking.switching;
18
Hyunsun Moonb974fca2016-06-30 21:20:39 -070019import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
jskimaa851932016-10-27 17:45:30 +090024import org.apache.felix.scr.annotations.Service;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070025import org.onlab.packet.Ethernet;
Hyunsun Moonb974fca2016-06-30 21:20:39 -070026import org.onlab.packet.Ip4Address;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070027import org.onlab.packet.IpAddress;
28import org.onosproject.core.ApplicationId;
29import org.onosproject.net.DeviceId;
Hyunsun Moonb974fca2016-06-30 21:20:39 -070030import org.onosproject.net.Host;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070031import org.onosproject.net.PortNumber;
Hyunsun Moonb974fca2016-06-30 21:20:39 -070032import org.onosproject.net.device.DeviceService;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070033import org.onosproject.net.flow.DefaultTrafficSelector;
34import org.onosproject.net.flow.DefaultTrafficTreatment;
35import org.onosproject.net.flow.TrafficSelector;
36import org.onosproject.net.flow.TrafficTreatment;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070037import org.onosproject.net.flowobjective.FlowObjectiveService;
38import org.onosproject.net.flowobjective.ForwardingObjective;
39import org.onosproject.openstacknetworking.AbstractVmHandler;
sangho91b50032017-01-06 18:16:21 +090040import org.onosproject.openstacknetworking.OpenstackSwitchingService;
41import org.onosproject.openstacknetworking.RulePopulatorUtil;
Hyunsun Moon05d9b262016-07-03 18:38:44 -070042import org.onosproject.openstacknode.OpenstackNodeService;
Hyunsun Moonb974fca2016-06-30 21:20:39 -070043import org.slf4j.Logger;
44import org.slf4j.LoggerFactory;
45
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070046import java.util.Optional;
Hyunsun Moonb974fca2016-06-30 21:20:39 -070047
sangho6032f342016-07-07 14:32:03 +090048import static org.onosproject.openstacknetworking.Constants.*;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070049import static org.onosproject.openstacknetworking.RulePopulatorUtil.buildExtension;
Hyunsun Moonb974fca2016-06-30 21:20:39 -070050
jskimaa851932016-10-27 17:45:30 +090051
Hyunsun Moonb974fca2016-06-30 21:20:39 -070052/**
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070053 * Populates switching flow rules.
Hyunsun Moonb974fca2016-06-30 21:20:39 -070054 */
jskimaa851932016-10-27 17:45:30 +090055@Service
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070056@Component(immediate = true)
jskimaa851932016-10-27 17:45:30 +090057public final class OpenstackSwitchingManager extends AbstractVmHandler
58 implements OpenstackSwitchingService {
Hyunsun Moonb974fca2016-06-30 21:20:39 -070059
60 private final Logger log = LoggerFactory.getLogger(getClass());
61
62 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonb974fca2016-06-30 21:20:39 -070063 protected DeviceService deviceService;
64
65 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070066 protected FlowObjectiveService flowObjectiveService;
Hyunsun Moonb974fca2016-06-30 21:20:39 -070067
68 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070069 protected OpenstackNodeService nodeService;
Hyunsun Moonb974fca2016-06-30 21:20:39 -070070
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070071 private ApplicationId appId;
Hyunsun Moonb974fca2016-06-30 21:20:39 -070072
73 @Activate
74 protected void activate() {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070075 super.activate();
76 appId = coreService.registerApplication(SWITCHING_APP_ID);
Hyunsun Moonb974fca2016-06-30 21:20:39 -070077 }
78
79 @Deactivate
80 protected void deactivate() {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070081 super.deactivate();
82 }
Hyunsun Moonb974fca2016-06-30 21:20:39 -070083
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070084 private void populateSwitchingRules(Host host) {
sangho91b50032017-01-06 18:16:21 +090085 setFlowRulesForTunnelTag(host, true);
86 setFlowRulesForTrafficToSameCnode(host, true);
87 setFlowRulesForTrafficToDifferentCnode(host, true);
Hyunsun Moonb974fca2016-06-30 21:20:39 -070088
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070089 log.debug("Populated switching rule for {}", host);
90 }
91
sangho91b50032017-01-06 18:16:21 +090092 private void removeSwitchingRules(Host host) {
93 setFlowRulesForTunnelTag(host, false);
94 setFlowRulesForTrafficToSameCnode(host, false);
95 setFlowRulesForTrafficToDifferentCnode(host, false);
96
97 log.debug("Removed switching rule for {}", host);
98 }
99
100 private void setFlowRulesForTunnelTag(Host host, boolean install) {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700101 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
102 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
103
104 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
105 .matchInPort(host.location().port());
106
107 tBuilder.setTunnelId(Long.valueOf(getVni(host)));
108
sangho91b50032017-01-06 18:16:21 +0900109 RulePopulatorUtil.setRule(flowObjectiveService, appId, host.location().deviceId(),
110 sBuilder.build(), tBuilder.build(), ForwardingObjective.Flag.SPECIFIC,
111 TUNNELTAG_RULE_PRIORITY, install);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700112 }
113
sangho91b50032017-01-06 18:16:21 +0900114 private void setFlowRulesForTrafficToSameCnode(Host host, boolean install) {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700115 //For L2 Switching Case
116 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
117 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
118
119 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
120 .matchIPDst(getIp(host).toIpPrefix())
121 .matchTunnelId(Long.valueOf(getVni(host)));
122
sanghofb3b5012016-11-10 15:47:53 +0900123 // Destination setting is required for routing cases.
124 // We do not believe the rule would not degrade the forwarding performance.
125 // But, if it does, we need to move the rule in a separate routing table.
126 tBuilder.setEthDst(host.mac())
127 .setOutput(host.location().port());
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700128
sangho91b50032017-01-06 18:16:21 +0900129 RulePopulatorUtil.setRule(flowObjectiveService, appId, host.location().deviceId(),
130 sBuilder.build(), tBuilder.build(), ForwardingObjective.Flag.SPECIFIC,
131 SWITCHING_RULE_PRIORITY, install);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700132 }
133
sangho91b50032017-01-06 18:16:21 +0900134 private void setFlowRulesForTrafficToDifferentCnode(Host host, boolean install) {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700135 Ip4Address localVmIp = getIp(host);
136 DeviceId localDeviceId = host.location().deviceId();
137 Optional<IpAddress> localDataIp = nodeService.dataIp(localDeviceId);
138
139 if (!localDataIp.isPresent()) {
140 log.debug("Failed to get data IP for device {}",
141 host.location().deviceId());
142 return;
143 }
144
145 String vni = getVni(host);
146 getVmsInDifferentCnode(host).forEach(remoteVm -> {
147 Optional<IpAddress> remoteDataIp = nodeService.dataIp(remoteVm.location().deviceId());
148 if (remoteDataIp.isPresent()) {
149 setVxLanFlowRule(vni,
150 localDeviceId,
151 remoteDataIp.get().getIp4Address(),
sangho91b50032017-01-06 18:16:21 +0900152 getIp(remoteVm), install);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700153
154 setVxLanFlowRule(vni,
155 remoteVm.location().deviceId(),
156 localDataIp.get().getIp4Address(),
sangho91b50032017-01-06 18:16:21 +0900157 localVmIp, install);
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700158 }
159 });
160 }
161
162 private void setVxLanFlowRule(String vni, DeviceId deviceId, Ip4Address remoteIp,
sangho91b50032017-01-06 18:16:21 +0900163 Ip4Address vmIp, boolean install) {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700164 Optional<PortNumber> tunnelPort = nodeService.tunnelPort(deviceId);
165 if (!tunnelPort.isPresent()) {
166 log.warn("Failed to get tunnel port from {}", deviceId);
167 return;
168 }
169
170 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
171 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
172
173 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
174 .matchTunnelId(Long.parseLong(vni))
175 .matchIPDst(vmIp.toIpPrefix());
176 tBuilder.extension(buildExtension(deviceService, deviceId, remoteIp), deviceId)
177 .setOutput(tunnelPort.get());
178
sangho91b50032017-01-06 18:16:21 +0900179 RulePopulatorUtil.setRule(flowObjectiveService, appId, deviceId,
180 sBuilder.build(), tBuilder.build(), ForwardingObjective.Flag.SPECIFIC,
181 SWITCHING_RULE_PRIORITY, install);
Hyunsun Moonb974fca2016-06-30 21:20:39 -0700182 }
183
184 @Override
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700185 protected void hostDetected(Host host) {
186 populateSwitchingRules(host);
187 log.info("Added new virtual machine to switching service {}", host);
Hyunsun Moonb974fca2016-06-30 21:20:39 -0700188 }
189
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700190 @Override
191 protected void hostRemoved(Host host) {
192 removeSwitchingRules(host);
193 log.info("Removed virtual machine from switching service {}", host);
Hyunsun Moon05d9b262016-07-03 18:38:44 -0700194 }
jskimaa851932016-10-27 17:45:30 +0900195
196 @Override
197 public void reinstallVmFlow(Host host) {
198 if (host == null) {
199 hostService.getHosts().forEach(h -> {
200 populateSwitchingRules(h);
201 log.info("Re-Install data plane flow of virtual machine {}", h);
202 });
203 } else {
204 populateSwitchingRules(host);
205 log.info("Re-Install data plane flow of virtual machine {}", host);
206 }
207 }
208
209 @Override
210 public void purgeVmFlow(Host host) {
211 if (host == null) {
212 hostService.getHosts().forEach(h -> {
213 removeSwitchingRules(h);
214 log.info("Purge data plane flow of virtual machine {}", h);
215 });
216 } else {
217 removeSwitchingRules(host);
218 log.info("Purge data plane flow of virtual machine {}", host);
219 }
220 }
Hyunsun Moonb974fca2016-06-30 21:20:39 -0700221}