blob: 1d4d4e130d96d4f6e53c984e3170717611014499 [file] [log] [blame]
Carolina Fernandezad893432016-07-18 11:11:34 +02001/*
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 */
16
17package org.onosproject.sdxl2;
18
19import com.google.common.collect.Iterables;
20import org.apache.commons.lang.NotImplementedException;
21import org.onlab.packet.VlanId;
22import org.onosproject.core.ApplicationId;
23import org.onosproject.net.flow.DefaultTrafficSelector;
24import org.onosproject.net.flow.DefaultTrafficTreatment;
25import org.onosproject.net.flow.TrafficSelector;
26import org.onosproject.net.flow.TrafficTreatment;
27import org.onosproject.net.intent.Constraint;
28import org.onosproject.net.intent.Intent;
29import org.onosproject.net.intent.IntentService;
30import org.onosproject.net.intent.Key;
31import org.slf4j.Logger;
32import org.slf4j.LoggerFactory;
33
34import java.util.ArrayList;
35import java.util.Collection;
36import java.util.List;
37import java.util.Objects;
38import java.util.Optional;
39import java.util.Set;
40
41import static java.lang.String.format;
42
43
44/**
45 * Manages Virtual Circuits.
46 * Base class extended by different types of VCs.
47 */
48public class SdxL2VCManager implements SdxL2VCService {
49
50 private static Logger log = LoggerFactory.getLogger(SdxL2VCManager.class);
51
52 protected static final String MATCH_FORMAT = "%s-%s";
53 protected static final String NAME_FORMAT = "%s:%s-%s";
54 protected static final String SDXL2_CPS_FORMAT = "%s~%s";
55 protected static final String KEY_FORMAT = "%s,%s";
56
57 protected ApplicationId appId;
58 protected SdxL2Store sdxL2Store;
59 protected IntentService intentService;
60
61 private static String errorIntentsForward = "Unable to create forward Intents";
62 private static String errorIntentsReverse = "Unable to create reverse Intents";
63 protected static String errorCreateIntents = "Unable to create Intents for %s-%s";
64
65
66 /**
67 * Creates an SDX-L2 VC Manager.
68 *
69 * @param sdxl2id application ID
70 * @param store reference to the SDX-L2 store
71 * @param intentService reference to the Intent service
72 */
73 public SdxL2VCManager(ApplicationId sdxl2id,
74 SdxL2Store store,
75 IntentService intentService) {
76
77 this.appId = sdxl2id;
78 this.sdxL2Store = store;
79 this.intentService = intentService;
80 }
81
82 @Override
83 public void addVC(String sdxl2, SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs) {
84 try {
85 this.sdxL2Store.addVC(sdxl2, sdxl2cplhs, sdxl2cprhs);
86
87 Collection<Intent> intentsFW = buildIntents(sdxl2, sdxl2cplhs, sdxl2cprhs);
88 Collection<Intent> intentsRV = buildIntents(sdxl2, sdxl2cprhs, sdxl2cplhs);
89
90 if (intentsFW == null) {
91 System.err.println("\u001B[0;31mError executing command: "
92 + errorIntentsForward + "\u001B[0;49m");
93 return;
94 }
95 if (intentsRV == null) {
96 System.err.println("\u001B[0;31mError executing command: "
97 + errorIntentsReverse + "\u001B[0;49m");
98 return;
99 }
100
101 List<Intent> intents = new ArrayList<Intent>();
102 intents.addAll(intentsFW);
103 intents.addAll(intentsRV);
104 intents.forEach(intent -> {
105 intentService.submit(intent);
106 });
107 } catch (SdxL2Exception e) {
108 log.error(e.getMessage());
109 }
110 }
111
112 @Override
113 public void removeVC(SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs) {
114 try {
115 this.sdxL2Store.removeVC(sdxl2cplhs, sdxl2cprhs);
116 Iterables.filter(intentService.getIntents(), intent ->
117 (matches(sdxl2cplhs, sdxl2cprhs, intent) ||
118 (matches(sdxl2cprhs, sdxl2cplhs, intent))))
119 .forEach(intentService::withdraw);
120 } catch (SdxL2Exception e) {
121 log.error(e.getMessage());
122 }
123 }
124
125 @Override
126 public void removeVC(SdxL2ConnectionPoint cp) {
127 try {
128 this.sdxL2Store.removeVC(cp);
129 Iterables.filter(intentService.getIntents(), intent -> (matches(cp, intent)))
130 .forEach(intentService::withdraw);
131 } catch (SdxL2Exception e) {
132 log.error(e.getMessage());
133 }
134 }
135
136 /**
137 * Creates a set of Intents for the ingress and egress SDX-L2 Connection Point.
138 *
139 * @param sdxl2 name of SDX-L2
140 * @param ingress the ingress point with the relative traffic attributes
141 * @param egress the egress point with the relative traffic attributes
142 * @return a set of intent or a null set;
143 */
144 public Collection<Intent> buildIntents(String sdxl2, SdxL2ConnectionPoint ingress,
145 SdxL2ConnectionPoint egress) {
146 throw new NotImplementedException("buildIntents not implemented");
147 }
148
149 /**
150 * Matches an intent given two SDX-L2 connection points.
151 *
152 * @param sdxl2cplhs left hand side of the virtual circuit
153 * @param sdxl2cprhs right hand side of the virtual circuit
154 * @param intent intent to match
155 * @return result of the match
156 */
157 protected boolean matches(SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs, Intent intent) {
158 if (!Objects.equals(appId, intent.appId())) {
159 // different app ids
160 return false;
161 }
162
163 String key = intent.key().toString();
164 String[] fields = key.split(":");
165 String cps = format(MATCH_FORMAT, sdxl2cplhs.name(), sdxl2cprhs.name());
166
167 return fields.length == 2 && fields[1].contains(cps);
168 }
169
170 /**
171 * Matches an intent given an SDX-L2 Connection Point.
172 *
173 * @param cp hand side of a Virtual Circuit
174 * @param intent intent to match
175 * @return result of the match
176 */
177 protected boolean matches(SdxL2ConnectionPoint cp, Intent intent) {
178 if (!Objects.equals(appId, intent.appId())) {
179 // different app ids
180 return false;
181 }
182
183 String key = intent.key().toString();
184 String[] fields = key.split(":");
185
186 if (fields.length != 2) {
187 return false;
188 }
189 String[] cps = fields[1].split(",");
190
191 if (cps.length != 2) {
192 return false;
193 }
194 String[] hss = cps[0].split("-");
195
196 return hss.length == 2 && (hss[0].equals(cp.name()) || hss[1].equals(cp.name()));
197 }
198
199 @Override
200 public void removeVCs(String sdxl2) {
201 this.sdxL2Store.removeVCs(sdxl2);
202 Iterables.filter(intentService.getIntents(), intent -> (matches(sdxl2, intent)))
203 .forEach(intentService::withdraw);
204
205 }
206
207 /**
208 * Matches an intent given an SDX-L2 Connection Point.
209 *
210 * @param sdxl2 name of SDX-L2
211 * @param intent intent to match
212 * @return result of the match
213 */
214 protected boolean matches(String sdxl2, Intent intent) {
215 if (!Objects.equals(appId, intent.appId())) {
216 // different app ids
217 return false;
218 }
219
220 String key = intent.key().toString();
221 String[] fields = key.split(":");
222
223 return fields.length == 2 && fields[0].equals(sdxl2);
224 }
225
226 @Override
227 public Set<String> getVCs(Optional<String> sdxl2) {
228 return this.sdxL2Store.getVCs(sdxl2);
229 }
230
231 @Override
232 public String getVC(SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs) {
233 try {
234 return this.sdxL2Store.getVC(sdxl2cplhs, sdxl2cprhs);
235 } catch (SdxL2Exception e) {
236 log.error(e.getMessage());
237 }
238 return null;
239 }
240
241 /**
242 * Returns Intent key from SDX-L2 and two SDX-L2 Connection Points.
243 *
244 * @param sdxl2 name of SDX-L2
245 * @param cpone sdxl2 connection point one
246 * @param cptwo sdxl2 connection point two
247 * @param index digit used to help identify Intent
248 * @return canonical intent string key
249 */
250 protected Key generateIntentKey(String sdxl2, SdxL2ConnectionPoint cpone,
251 SdxL2ConnectionPoint cptwo, String index) {
252 String cps = format(NAME_FORMAT, sdxl2, cpone.name(), cptwo.name());
253 String key = format(KEY_FORMAT, cps, index);
254 return Key.of(key, appId);
255 }
256
257 /**
258 * Returns the traffic treatment, used in the definition of the intents.
259 *
260 * @param setVlan VLAN to set
261 * @param pushVlan VLAN to push
262 * @param popVlan boolean to indicate whether a popVlan action is
263 * performed (true) or not (false)
264 * @return TrafficTreatment object
265 */
266 protected TrafficTreatment buildTreatment(VlanId setVlan,
267 VlanId pushVlan,
268 boolean popVlan) {
269 TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
270 if (setVlan != null) {
271 treatmentBuilder.setVlanId(setVlan);
272 }
273 if (pushVlan != null) {
274 treatmentBuilder.pushVlan();
275 treatmentBuilder.setVlanId(pushVlan);
276 }
277 if (popVlan) {
278 treatmentBuilder.popVlan();
279 }
280 return treatmentBuilder.build();
281 }
282
283 /**
284 * Returns the traffic selector, used in the definition of the intents.
285 *
286 * @param ethertype name of the Ethernet type used (e.g. of SDX-L2
287 * @param ingresstag VLAN id used at the ingress
288 * @return TrafficSelector object
289 */
290 protected TrafficSelector buildSelector(Short ethertype, VlanId ingresstag) {
291 TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
292 if (ethertype != null) {
293 selectorBuilder.matchEthType(ethertype);
294 }
295 if (ingresstag != null) {
296 selectorBuilder.matchVlanId(ingresstag);
297 }
298 return selectorBuilder.build();
299 }
300
301 /**
302 * Returns constraints depending on the encapsulation used on the VC.
303 *
304 * @return list of constraints to be used in the intents
305 */
306 protected List<Constraint> buildConstraints() {
307 throw new NotImplementedException("buildConstraints not implemented");
308 }
309}