blob: 33548726e718eb749921a6587e41d8bcbc515deb [file] [log] [blame]
/*
* Copyright 2016-present Open Networking Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.sdxl2;
import com.google.common.collect.Iterables;
import org.apache.commons.lang.NotImplementedException;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.intent.Constraint;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.Key;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import static java.lang.String.format;
/**
* Manages Virtual Circuits.
* Base class extended by different types of VCs.
*/
public class SdxL2VCManager implements SdxL2VCService {
private static Logger log = LoggerFactory.getLogger(SdxL2VCManager.class);
protected static final String NAME_FORMAT = "%s:%s-%s";
protected static final String SDXL2_CPS_FORMAT = "%s~%s";
private static final String KEY_FORMAT = "%s,%s";
protected ApplicationId appId;
protected SdxL2Store sdxL2Store;
protected IntentService intentService;
private SdxL2ConnectionPointMatcher matcher;
private static final String ERROR_INTENTS_FORWARD = "Unable to create forward Intents";
private static final String ERROR_INTENTS_REVERSE = "Unable to create reverse Intents";
protected static final String ERROR_CREATE_INTENTS = "Unable to create Intents for %s-%s";
/**
* Creates a SDX-L2 VC Manager.
*
* @param sdxl2id application ID
* @param store reference to the SDX-L2 store
* @param intentService reference to the Intent service
*/
public SdxL2VCManager(ApplicationId sdxl2id,
SdxL2Store store,
IntentService intentService) {
this.appId = sdxl2id;
this.sdxL2Store = store;
this.intentService = intentService;
this.matcher = new SdxL2ConnectionPointMatcher(sdxl2id);
}
@Override
public void addVC(String sdxl2, SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs) {
try {
this.sdxL2Store.addVC(sdxl2, sdxl2cplhs, sdxl2cprhs);
Collection<Intent> intentsFW = buildIntents(sdxl2, sdxl2cplhs, sdxl2cprhs);
Collection<Intent> intentsRV = buildIntents(sdxl2, sdxl2cprhs, sdxl2cplhs);
if (intentsFW == null) {
System.err.println("\u001B[0;31mError executing command: "
+ ERROR_INTENTS_FORWARD + "\u001B[0;49m");
return;
}
if (intentsRV == null) {
System.err.println("\u001B[0;31mError executing command: "
+ ERROR_INTENTS_REVERSE + "\u001B[0;49m");
return;
}
List<Intent> intents = new ArrayList<>();
intents.addAll(intentsFW);
intents.addAll(intentsRV);
intents.forEach(intent -> intentService.submit(intent));
} catch (SdxL2Exception e) {
log.error(e.getMessage());
}
}
@Override
public void removeVC(SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs) {
try {
this.sdxL2Store.removeVC(sdxl2cplhs, sdxl2cprhs);
Iterables.filter(intentService.getIntents(), intent ->
(matcher.matches(sdxl2cplhs, sdxl2cprhs, intent) ||
(matcher.matches(sdxl2cprhs, sdxl2cplhs, intent))))
.forEach(intentService::withdraw);
} catch (SdxL2Exception e) {
log.error(e.getMessage());
}
}
@Override
public void removeVC(SdxL2ConnectionPoint cp) {
try {
this.sdxL2Store.removeVC(cp);
Iterables.filter(intentService.getIntents(), intent -> (matcher.matches(cp, intent)))
.forEach(intentService::withdraw);
} catch (SdxL2Exception e) {
log.error(e.getMessage());
}
}
/**
* Creates a set of Intents for the ingress and egress SDX-L2 Connection Point.
*
* @param sdxl2 name of SDX-L2
* @param ingress the ingress point with the relative traffic attributes
* @param egress the egress point with the relative traffic attributes
* @return a set of intent or a null set;
*/
public Collection<Intent> buildIntents(String sdxl2, SdxL2ConnectionPoint ingress,
SdxL2ConnectionPoint egress) {
throw new NotImplementedException("buildIntents not implemented");
}
@Override
public void removeVCs(String sdxl2) {
this.sdxL2Store.removeVCs(sdxl2);
Iterables.filter(intentService.getIntents(), intent -> (matcher.matches(sdxl2, intent)))
.forEach(intentService::withdraw);
}
@Override
public Set<String> getVCs(Optional<String> sdxl2) {
return this.sdxL2Store.getVCs(sdxl2);
}
@Override
public String getVC(SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs) {
try {
return this.sdxL2Store.getVC(sdxl2cplhs, sdxl2cprhs);
} catch (SdxL2Exception e) {
log.error(e.getMessage());
}
return null;
}
/**
* Returns Intent key from SDX-L2 and two SDX-L2 Connection Points.
*
* @param sdxl2 name of SDX-L2
* @param cpOne sdxl2 connection point one
* @param cpTwo sdxl2 connection point two
* @param index digit used to help identify Intent
* @return canonical intent string key
*/
protected Key generateIntentKey(String sdxl2, SdxL2ConnectionPoint cpOne,
SdxL2ConnectionPoint cpTwo, String index) {
String cps = format(NAME_FORMAT, sdxl2, cpOne.name(), cpTwo.name());
String key = format(KEY_FORMAT, cps, index);
return Key.of(key, appId);
}
/**
* Returns the traffic treatment, used in the definition of the intents.
*
* @param setVlan VLAN to set
* @param pushVlan VLAN to push
* @param popVlan boolean to indicate whether a popVlan action is
* performed (true) or not (false)
* @return TrafficTreatment object
*/
protected TrafficTreatment buildTreatment(VlanId setVlan,
VlanId pushVlan,
boolean popVlan) {
TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
if (setVlan != null) {
treatmentBuilder.setVlanId(setVlan);
}
if (pushVlan != null) {
treatmentBuilder.pushVlan();
treatmentBuilder.setVlanId(pushVlan);
}
if (popVlan) {
treatmentBuilder.popVlan();
}
return treatmentBuilder.build();
}
/**
* Returns the traffic selector, used in the definition of the intents.
*
* @param ethertype name of the Ethernet type used (e.g. of SDX-L2
* @param ingresstag VLAN id used at the ingress
* @return TrafficSelector object
*/
protected TrafficSelector buildSelector(Short ethertype, VlanId ingresstag) {
TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
if (ethertype != null) {
selectorBuilder.matchEthType(ethertype);
}
if (ingresstag != null) {
selectorBuilder.matchVlanId(ingresstag);
}
return selectorBuilder.build();
}
/**
* Returns constraints depending on the encapsulation used on the VC.
*
* @return list of constraints to be used in the intents
*/
protected List<Constraint> buildConstraints() {
throw new NotImplementedException("buildConstraints not implemented");
}
}