blob: 98673cfc2350cd3668564f9779450b5bf040eec5 [file] [log] [blame]
Hyunsun Moon60a10672016-06-12 17:39:12 -07001/*
2 * 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 */
Hyunsun Moon5401aaa2016-06-12 17:40:34 -070016package org.opencord.cordvtn.impl.handler;
Hyunsun Moon60a10672016-06-12 17:39:12 -070017
18import org.apache.felix.scr.annotations.Activate;
19import org.apache.felix.scr.annotations.Component;
20
21import org.apache.felix.scr.annotations.Deactivate;
Hyunsun Moon5401aaa2016-06-12 17:40:34 -070022import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
Hyunsun Moon60a10672016-06-12 17:39:12 -070024import org.onlab.packet.Ethernet;
25import org.onlab.packet.Ip4Address;
26import org.onlab.packet.Ip4Prefix;
27import org.onosproject.net.flow.DefaultFlowRule;
28import org.onosproject.net.flow.DefaultTrafficSelector;
29import org.onosproject.net.flow.DefaultTrafficTreatment;
30import org.onosproject.net.flow.FlowRule;
31import org.onosproject.net.flow.TrafficSelector;
32import org.onosproject.net.flow.TrafficTreatment;
33import org.onosproject.net.flow.instructions.ExtensionTreatment;
34import org.opencord.cordvtn.impl.AbstractInstanceHandler;
35import org.opencord.cordvtn.api.CordVtnNode;
36import org.opencord.cordvtn.api.Instance;
37import org.opencord.cordvtn.api.InstanceHandler;
38import org.onosproject.xosclient.api.VtnService;
Hyunsun Moon5401aaa2016-06-12 17:40:34 -070039import org.opencord.cordvtn.impl.CordVtnNodeManager;
Hyunsun Moon60a10672016-06-12 17:39:12 -070040import org.opencord.cordvtn.impl.CordVtnPipeline;
41
42import java.util.Optional;
43
Hyunsun Moon60a10672016-06-12 17:39:12 -070044import static org.onosproject.xosclient.api.VtnServiceApi.ServiceType.DEFAULT;
45
46/**
47 * Provides network connectivity for default service instances.
48 */
49@Component(immediate = true)
50public class DefaultInstanceHandler extends AbstractInstanceHandler implements InstanceHandler {
51
Hyunsun Moon5401aaa2016-06-12 17:40:34 -070052 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
53 protected CordVtnPipeline pipeline;
54
55 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
56 protected CordVtnNodeManager nodeManager;
57
Hyunsun Moon60a10672016-06-12 17:39:12 -070058 @Activate
59 protected void activate() {
60 serviceType = Optional.of(DEFAULT);
Hyunsun Moon60a10672016-06-12 17:39:12 -070061 super.activate();
62 }
63
64 @Deactivate
65 protected void deactivate() {
66 super.deactivate();
67 }
68
69 @Override
70 public void instanceDetected(Instance instance) {
71 log.info("Instance is detected {}", instance);
72
73 VtnService service = getVtnService(instance.serviceId());
74 if (service == null) {
75 log.warn("Failed to get VtnService for {}", instance);
76 return;
77 }
78 defaultConnectionRules(instance, service, true);
79 }
80
81 @Override
82 public void instanceRemoved(Instance instance) {
83 log.info("Instance is removed {}", instance);
84
85 VtnService service = getVtnService(instance.serviceId());
86 if (service == null) {
87 log.warn("Failed to get VtnService for {}", instance);
88 return;
89 }
90 defaultConnectionRules(instance, service, false);
91 }
92
93 private void defaultConnectionRules(Instance instance, VtnService service, boolean install) {
94 long vni = service.vni();
95 Ip4Prefix serviceIpRange = service.subnet().getIp4Prefix();
96
97 inPortRule(instance, install);
98 dstIpRule(instance, vni, install);
99 tunnelInRule(instance, vni, install);
100
101 if (install) {
102 directAccessRule(serviceIpRange, serviceIpRange, true);
103 serviceIsolationRule(serviceIpRange, true);
104 } else if (getInstances(service.id()).isEmpty()) {
105 directAccessRule(serviceIpRange, serviceIpRange, false);
106 serviceIsolationRule(serviceIpRange, false);
107 }
108 }
109
110 private void inPortRule(Instance instance, boolean install) {
111 TrafficSelector selector = DefaultTrafficSelector.builder()
112 .matchInPort(instance.portNumber())
113 .matchEthType(Ethernet.TYPE_IPV4)
114 .matchIPSrc(instance.ipAddress().toIpPrefix())
115 .build();
116
117 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
118 .transition(CordVtnPipeline.TABLE_ACCESS_TYPE)
119 .build();
120
Hyunsun Moon60a10672016-06-12 17:39:12 -0700121 FlowRule flowRule = DefaultFlowRule.builder()
122 .fromApp(appId)
123 .withSelector(selector)
124 .withTreatment(treatment)
125 .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
126 .forDevice(instance.deviceId())
127 .forTable(CordVtnPipeline.TABLE_IN_PORT)
128 .makePermanent()
129 .build();
130
131 pipeline.processFlowRule(install, flowRule);
132
133 selector = DefaultTrafficSelector.builder()
134 .matchInPort(instance.portNumber())
135 .build();
136
137 treatment = DefaultTrafficTreatment.builder()
138 .transition(CordVtnPipeline.TABLE_IN_SERVICE)
139 .build();
140
141 flowRule = DefaultFlowRule.builder()
142 .fromApp(appId)
143 .withSelector(selector)
144 .withTreatment(treatment)
145 .withPriority(CordVtnPipeline.PRIORITY_LOW)
146 .forDevice(instance.deviceId())
147 .forTable(CordVtnPipeline.TABLE_IN_PORT)
148 .makePermanent()
149 .build();
150
151 pipeline.processFlowRule(install, flowRule);
152 }
153
154 private void dstIpRule(Instance instance, long vni, boolean install) {
155 Ip4Address tunnelIp = nodeManager.dpIp(instance.deviceId()).getIp4Address();
156
157 TrafficSelector selector = DefaultTrafficSelector.builder()
158 .matchEthType(Ethernet.TYPE_IPV4)
159 .matchIPDst(instance.ipAddress().toIpPrefix())
160 .build();
161
162 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
163 .setEthDst(instance.mac())
164 .setOutput(instance.portNumber())
165 .build();
166
167 FlowRule flowRule = DefaultFlowRule.builder()
168 .fromApp(appId)
169 .withSelector(selector)
170 .withTreatment(treatment)
171 .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
172 .forDevice(instance.deviceId())
173 .forTable(CordVtnPipeline.TABLE_DST_IP)
174 .makePermanent()
175 .build();
176
177 pipeline.processFlowRule(install, flowRule);
178
179 for (CordVtnNode node : nodeManager.completeNodes()) {
180 if (node.intBrId().equals(instance.deviceId())) {
181 continue;
182 }
183
184 ExtensionTreatment tunnelDst = pipeline.tunnelDstTreatment(node.intBrId(), tunnelIp);
185 if (tunnelDst == null) {
186 continue;
187 }
188
189 treatment = DefaultTrafficTreatment.builder()
190 .setEthDst(instance.mac())
191 .setTunnelId(vni)
192 .extension(tunnelDst, node.intBrId())
193 .setOutput(nodeManager.tunnelPort(node.intBrId()))
194 .build();
195
196 flowRule = DefaultFlowRule.builder()
197 .fromApp(appId)
198 .withSelector(selector)
199 .withTreatment(treatment)
200 .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
201 .forDevice(node.intBrId())
202 .forTable(CordVtnPipeline.TABLE_DST_IP)
203 .makePermanent()
204 .build();
205
206 pipeline.processFlowRule(install, flowRule);
207 }
208 }
209
210 private void tunnelInRule(Instance instance, long vni, boolean install) {
211 TrafficSelector selector = DefaultTrafficSelector.builder()
212 .matchTunnelId(vni)
213 .matchEthDst(instance.mac())
214 .build();
215
216 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
217 .setOutput(instance.portNumber())
218 .build();
219
220 FlowRule flowRule = DefaultFlowRule.builder()
221 .fromApp(appId)
222 .withSelector(selector)
223 .withTreatment(treatment)
224 .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
225 .forDevice(instance.deviceId())
226 .forTable(CordVtnPipeline.TABLE_TUNNEL_IN)
227 .makePermanent()
228 .build();
229
230 pipeline.processFlowRule(install, flowRule);
231 }
232
233 private void directAccessRule(Ip4Prefix srcRange, Ip4Prefix dstRange, boolean install) {
234 TrafficSelector selector = DefaultTrafficSelector.builder()
235 .matchEthType(Ethernet.TYPE_IPV4)
236 .matchIPSrc(srcRange)
237 .matchIPDst(dstRange)
238 .build();
239
240 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
241 .transition(CordVtnPipeline.TABLE_DST_IP)
242 .build();
243
244
245 nodeManager.completeNodes().stream().forEach(node -> {
246 FlowRule flowRuleDirect = DefaultFlowRule.builder()
247 .fromApp(appId)
248 .withSelector(selector)
249 .withTreatment(treatment)
250 .withPriority(CordVtnPipeline.PRIORITY_DEFAULT)
251 .forDevice(node.intBrId())
252 .forTable(CordVtnPipeline.TABLE_ACCESS_TYPE)
253 .makePermanent()
254 .build();
255
256 pipeline.processFlowRule(install, flowRuleDirect);
257 });
258 }
259
260 private void serviceIsolationRule(Ip4Prefix dstRange, boolean install) {
261 TrafficSelector selector = DefaultTrafficSelector.builder()
262 .matchEthType(Ethernet.TYPE_IPV4)
263 .matchIPDst(dstRange)
264 .build();
265
266 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
267 .drop()
268 .build();
269
270 nodeManager.completeNodes().stream().forEach(node -> {
271 FlowRule flowRuleDirect = DefaultFlowRule.builder()
272 .fromApp(appId)
273 .withSelector(selector)
274 .withTreatment(treatment)
275 .withPriority(CordVtnPipeline.PRIORITY_LOW)
276 .forDevice(node.intBrId())
277 .forTable(CordVtnPipeline.TABLE_ACCESS_TYPE)
278 .makePermanent()
279 .build();
280
281 pipeline.processFlowRule(install, flowRuleDirect);
282 });
283 }
284}