blob: 59b41ff81431622863cee659517aeb826aae815f [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;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070024import org.onlab.packet.Ethernet;
Hyunsun Moonb974fca2016-06-30 21:20:39 -070025import org.onlab.packet.Ip4Address;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070026import org.onlab.packet.IpAddress;
27import org.onosproject.core.ApplicationId;
28import org.onosproject.net.DeviceId;
Hyunsun Moonb974fca2016-06-30 21:20:39 -070029import org.onosproject.net.Host;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070030import org.onosproject.net.PortNumber;
Hyunsun Moonb974fca2016-06-30 21:20:39 -070031import org.onosproject.net.device.DeviceService;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070032import org.onosproject.net.flow.DefaultTrafficSelector;
33import org.onosproject.net.flow.DefaultTrafficTreatment;
34import org.onosproject.net.flow.TrafficSelector;
35import org.onosproject.net.flow.TrafficTreatment;
36import org.onosproject.net.flowobjective.DefaultForwardingObjective;
37import org.onosproject.net.flowobjective.FlowObjectiveService;
38import org.onosproject.net.flowobjective.ForwardingObjective;
39import org.onosproject.openstacknetworking.AbstractVmHandler;
Hyunsun Moon05d9b262016-07-03 18:38:44 -070040import org.onosproject.openstacknode.OpenstackNodeService;
Hyunsun Moonb974fca2016-06-30 21:20:39 -070041import org.slf4j.Logger;
42import org.slf4j.LoggerFactory;
43
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070044import java.util.Objects;
45import java.util.Optional;
Hyunsun Moonb974fca2016-06-30 21:20:39 -070046
sangho6032f342016-07-07 14:32:03 +090047import static org.onosproject.openstacknetworking.Constants.*;
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070048import static org.onosproject.openstacknetworking.RulePopulatorUtil.buildExtension;
Hyunsun Moonb974fca2016-06-30 21:20:39 -070049
Hyunsun Moonb974fca2016-06-30 21:20:39 -070050/**
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070051 * Populates switching flow rules.
Hyunsun Moonb974fca2016-06-30 21:20:39 -070052 */
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070053@Component(immediate = true)
54public final class OpenstackSwitchingManager extends AbstractVmHandler {
Hyunsun Moonb974fca2016-06-30 21:20:39 -070055
56 private final Logger log = LoggerFactory.getLogger(getClass());
57
58 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonb974fca2016-06-30 21:20:39 -070059 protected DeviceService deviceService;
60
61 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070062 protected FlowObjectiveService flowObjectiveService;
Hyunsun Moonb974fca2016-06-30 21:20:39 -070063
64 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070065 protected OpenstackNodeService nodeService;
Hyunsun Moonb974fca2016-06-30 21:20:39 -070066
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070067 private ApplicationId appId;
Hyunsun Moonb974fca2016-06-30 21:20:39 -070068
69 @Activate
70 protected void activate() {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070071 super.activate();
72 appId = coreService.registerApplication(SWITCHING_APP_ID);
Hyunsun Moonb974fca2016-06-30 21:20:39 -070073 }
74
75 @Deactivate
76 protected void deactivate() {
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070077 super.deactivate();
78 }
Hyunsun Moonb974fca2016-06-30 21:20:39 -070079
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070080 private void populateSwitchingRules(Host host) {
81 populateFlowRulesForTunnelTag(host);
82 populateFlowRulesForTrafficToSameCnode(host);
83 populateFlowRulesForTrafficToDifferentCnode(host);
Hyunsun Moonb974fca2016-06-30 21:20:39 -070084
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -070085 log.debug("Populated switching rule for {}", host);
86 }
87
88 private void populateFlowRulesForTunnelTag(Host host) {
89 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
90 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
91
92 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
93 .matchInPort(host.location().port());
94
95 tBuilder.setTunnelId(Long.valueOf(getVni(host)));
96
97 ForwardingObjective fo = DefaultForwardingObjective.builder()
98 .withSelector(sBuilder.build())
99 .withTreatment(tBuilder.build())
100 .withPriority(TUNNELTAG_RULE_PRIORITY)
101 .withFlag(ForwardingObjective.Flag.SPECIFIC)
102 .fromApp(appId)
103 .add();
104
105 flowObjectiveService.forward(host.location().deviceId(), fo);
106 }
107
108 private void populateFlowRulesForTrafficToSameCnode(Host host) {
109 //For L2 Switching Case
110 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
111 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
112
113 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
114 .matchIPDst(getIp(host).toIpPrefix())
115 .matchTunnelId(Long.valueOf(getVni(host)));
116
117 tBuilder.setOutput(host.location().port());
118
119 ForwardingObjective fo = DefaultForwardingObjective.builder()
120 .withSelector(sBuilder.build())
121 .withTreatment(tBuilder.build())
122 .withPriority(SWITCHING_RULE_PRIORITY)
123 .withFlag(ForwardingObjective.Flag.SPECIFIC)
124 .fromApp(appId)
125 .add();
126
127 flowObjectiveService.forward(host.location().deviceId(), fo);
128 }
129
130 private void populateFlowRulesForTrafficToDifferentCnode(Host host) {
131 Ip4Address localVmIp = getIp(host);
132 DeviceId localDeviceId = host.location().deviceId();
133 Optional<IpAddress> localDataIp = nodeService.dataIp(localDeviceId);
134
135 if (!localDataIp.isPresent()) {
136 log.debug("Failed to get data IP for device {}",
137 host.location().deviceId());
138 return;
139 }
140
141 String vni = getVni(host);
142 getVmsInDifferentCnode(host).forEach(remoteVm -> {
143 Optional<IpAddress> remoteDataIp = nodeService.dataIp(remoteVm.location().deviceId());
144 if (remoteDataIp.isPresent()) {
145 setVxLanFlowRule(vni,
146 localDeviceId,
147 remoteDataIp.get().getIp4Address(),
148 getIp(remoteVm));
149
150 setVxLanFlowRule(vni,
151 remoteVm.location().deviceId(),
152 localDataIp.get().getIp4Address(),
153 localVmIp);
154 }
155 });
156 }
157
158 private void setVxLanFlowRule(String vni, DeviceId deviceId, Ip4Address remoteIp,
159 Ip4Address vmIp) {
160 Optional<PortNumber> tunnelPort = nodeService.tunnelPort(deviceId);
161 if (!tunnelPort.isPresent()) {
162 log.warn("Failed to get tunnel port from {}", deviceId);
163 return;
164 }
165
166 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
167 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
168
169 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
170 .matchTunnelId(Long.parseLong(vni))
171 .matchIPDst(vmIp.toIpPrefix());
172 tBuilder.extension(buildExtension(deviceService, deviceId, remoteIp), deviceId)
173 .setOutput(tunnelPort.get());
174
175 ForwardingObjective fo = DefaultForwardingObjective.builder()
176 .withSelector(sBuilder.build())
177 .withTreatment(tBuilder.build())
178 .withPriority(SWITCHING_RULE_PRIORITY)
179 .withFlag(ForwardingObjective.Flag.SPECIFIC)
180 .fromApp(appId)
181 .add();
182
183 flowObjectiveService.forward(deviceId, fo);
184 }
185
186 private void removeSwitchingRules(Host host) {
187 removeFlowRuleForTunnelTag(host);
188 removeFlowRuleForVMsInSameCnode(host);
189 removeFlowRuleForVMsInDiffrentCnode(host);
190
191 log.debug("Removed switching rule for {}", host);
192 }
193
194 private void removeFlowRuleForTunnelTag(Host host) {
195 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
196 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
197
198 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
199 .matchInPort(host.location().port());
200
201 ForwardingObjective fo = DefaultForwardingObjective.builder()
202 .withSelector(sBuilder.build())
203 .withTreatment(tBuilder.build())
204 .withPriority(TUNNELTAG_RULE_PRIORITY)
205 .withFlag(ForwardingObjective.Flag.SPECIFIC)
206 .fromApp(appId)
207 .remove();
208
209 flowObjectiveService.forward(host.location().deviceId(), fo);
210 }
211
212 private void removeFlowRuleForVMsInSameCnode(Host host) {
213 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
214 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
215 .matchIPDst(getIp(host).toIpPrefix())
216 .matchTunnelId(Long.valueOf(getVni(host)));
217
218 ForwardingObjective fo = DefaultForwardingObjective.builder()
219 .withSelector(sBuilder.build())
220 .withTreatment(DefaultTrafficTreatment.builder().build())
221 .withFlag(ForwardingObjective.Flag.SPECIFIC)
222 .withPriority(SWITCHING_RULE_PRIORITY)
223 .fromApp(appId)
224 .remove();
225
226 flowObjectiveService.forward(host.location().deviceId(), fo);
227 }
228
229 private void removeFlowRuleForVMsInDiffrentCnode(Host host) {
230 DeviceId deviceId = host.location().deviceId();
231 final boolean anyPortRemainedInSameCnode = hostService.getConnectedHosts(deviceId)
232 .stream()
233 .filter(this::isValidHost)
234 .anyMatch(h -> Objects.equals(getVni(h), getVni(host)));
235
236 getVmsInDifferentCnode(host).forEach(h -> {
237 removeVxLanFlowRule(h.location().deviceId(), getIp(host), getVni(host));
238 if (!anyPortRemainedInSameCnode) {
239 removeVxLanFlowRule(deviceId, getIp(h), getVni(host));
240 }
241 });
242 }
243
244 private void removeVxLanFlowRule(DeviceId deviceId, Ip4Address vmIp, String vni) {
245 TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
246
247 sBuilder.matchEthType(Ethernet.TYPE_IPV4)
248 .matchTunnelId(Long.valueOf(vni))
249 .matchIPDst(vmIp.toIpPrefix());
250
251 ForwardingObjective fo = DefaultForwardingObjective.builder()
252 .withSelector(sBuilder.build())
253 .withTreatment(DefaultTrafficTreatment.builder().build())
254 .withFlag(ForwardingObjective.Flag.SPECIFIC)
255 .withPriority(SWITCHING_RULE_PRIORITY)
256 .fromApp(appId)
257 .remove();
258
259 flowObjectiveService.forward(deviceId, fo);
Hyunsun Moonb974fca2016-06-30 21:20:39 -0700260 }
261
262 @Override
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700263 protected void hostDetected(Host host) {
264 populateSwitchingRules(host);
265 log.info("Added new virtual machine to switching service {}", host);
Hyunsun Moonb974fca2016-06-30 21:20:39 -0700266 }
267
Hyunsun Moonb3eb84d2016-07-27 19:10:52 -0700268 @Override
269 protected void hostRemoved(Host host) {
270 removeSwitchingRules(host);
271 log.info("Removed virtual machine from switching service {}", host);
Hyunsun Moon05d9b262016-07-03 18:38:44 -0700272 }
Hyunsun Moonb974fca2016-06-30 21:20:39 -0700273}