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