blob: 2ecc70fe3e435e64576147a7c81661dceeb47a36 [file] [log] [blame]
/*
* Copyright 2017-present Open Networking Laboratory
*
* 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.drivers.microsemi;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onosproject.core.CoreService;
import org.onosproject.drivers.microsemi.yang.MseaUniEvcServiceNetconfService;
import org.onosproject.net.DeviceId;
import org.onosproject.net.meter.Band;
import org.onosproject.net.meter.Meter.Unit;
import org.onosproject.net.meter.MeterOperation;
import org.onosproject.net.meter.MeterOperations;
import org.onosproject.net.meter.MeterProvider;
import org.onosproject.net.meter.MeterProviderRegistry;
import org.onosproject.net.meter.MeterProviderService;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.netconf.NetconfController;
import org.onosproject.netconf.NetconfException;
import org.onosproject.netconf.NetconfSession;
import org.onosproject.netconf.TargetConfig;
import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.types.rev20160229.mseatypes.CosColorType;
import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.types.rev20160229.mseatypes.PriorityType;
import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.types.rev20160229.mseatypes.coscolortype.CosColorTypeEnum;
import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.MseaUniEvcService;
import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.MseaUniEvcService.OnosYangOpType;
import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.MseaUniEvcServiceOpParam;
import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.DefaultMefServices;
import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.MefServices;
import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.DefaultProfiles;
import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.DefaultProfiles.ProfilesBuilder;
import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.BwpGroup;
import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.Cos;
import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.DefaultBwpGroup;
import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.DefaultCos;
import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.bwpgroup.Bwp;
import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.bwpgroup.DefaultBwp;
import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.DefaultEvcCosTypeEvcColorId;
import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.evccostypeevccolorid.DefaultEvcCosTypeAll8PrioTo1EvcColor;
import org.onosproject.yang.gen.v1.http.www.microsemi.com.microsemi.edge.assure.msea.uni.evc.service.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.evccostypeevccolorid.EvcCosTypeAll8PrioTo1EvcColor;
import org.slf4j.Logger;
/**
* Provider which uses an NETCONF controller to handle meters.
*/
@Component(immediate = true, enabled = true)
public class EA1000MeterProvider extends AbstractProvider implements MeterProvider {
private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected NetconfController controller;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected MeterProviderRegistry providerRegistry;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected MseaUniEvcServiceNetconfService mseaUniEvcServiceSvc;
private MeterProviderService providerService;
private static final int COS_INDEX_1 = 1;
private static final short DEFAULT_OUTGOING_PRIO = 3;
/**
* Creates a OpenFlow meter provider.
*/
public EA1000MeterProvider() {
super(new ProviderId("netconf", "org.onosproject.provider.meter.microsemi"));
}
@Activate
public void activate() {
providerService = providerRegistry.register(this);
}
@Deactivate
public void deactivate() {
providerRegistry.unregister(this);
providerService = null;
}
@Override
public void performMeterOperation(DeviceId deviceId, MeterOperations meterOps) {
log.debug("Adding meterOps to Microsemi Meter Store");
}
@Override
public void performMeterOperation(DeviceId deviceId, MeterOperation meterOp) {
if (meterOp == null || deviceId == null) {
log.warn("Missing argument for performMeterOperation()");
return;
}
log.debug("{} meterOp {} to Microsemi Meter Store", meterOp.type(), meterOp);
long meterId = meterOp.meter().id().id();
String deviceName = deviceId.uri().getSchemeSpecificPart();
Unit unit = meterOp.meter().unit();
ProfilesBuilder profilesBuilder = DefaultProfiles.builder();
if (meterOp.type() == MeterOperation.Type.ADD || meterOp.type() == MeterOperation.Type.MODIFY) {
Bwp.BwpBuilder bwpBuilder = DefaultBwp.builder()
.cosIndex(COS_INDEX_1)
.name("BWP-" + String.valueOf(meterId) + "-" + deviceName);
long cirRateKbps = 0L;
long cbsRateKbps = 0L;
long eirRateKbps = 0L;
long ebsRateKbps = 0L;
for (Band band:meterOp.meter().bands()) {
if (band.type() == Band.Type.REMARK) {
//This relates to CIR/CBS
cirRateKbps = toBitsPerSec(band.rate(), unit);
cbsRateKbps = band.burst(); //Already in kbps
} else if (band.type() == Band.Type.DROP) {
//This relates to EIR/EBS
eirRateKbps = toBitsPerSec(band.rate(), unit);
ebsRateKbps = band.burst(); //Already in kbps
}
}
bwpBuilder.committedInformationRate(cirRateKbps).excessInformationRate(eirRateKbps - cirRateKbps);
if (meterOp.meter().isBurst()) {
bwpBuilder.committedBurstSize(cbsRateKbps).excessBurstSize(ebsRateKbps - cbsRateKbps);
}
BwpGroup.BwpGroupBuilder bwpgBuilder =
DefaultBwpGroup.builder()
.groupIndex((short) meterId)
.addToBwp(bwpBuilder.build());
//Create cos-1 as referenced above - we only support 1 at the moment
Cos.CosBuilder cosBuilder = DefaultCos.builder()
.cosIndex(COS_INDEX_1)
.name("COS-1")
.outgoingCosValue(PriorityType.of(DEFAULT_OUTGOING_PRIO))
.colorAware(true)
.colorForward(true);
EvcCosTypeAll8PrioTo1EvcColor ect =
DefaultEvcCosTypeAll8PrioTo1EvcColor.builder()
.evcAll8ColorTo(CosColorType.of(CosColorTypeEnum.GREEN)).build();
profilesBuilder
.addToBwpGroup(bwpgBuilder.build())
.addToCos(cosBuilder.cosTypeChoice(
DefaultEvcCosTypeEvcColorId.builder()
.evcCosTypeAll8PrioTo1EvcColor(ect).build()).build())
.build();
} else if (meterOp.type() == MeterOperation.Type.REMOVE) {
BwpGroup.BwpGroupBuilder bwpgBuilder =
DefaultBwpGroup.builder()
.groupIndex((short) meterId)
.yangBwpGroupOpType(OnosYangOpType.DELETE);
profilesBuilder.addToBwpGroup(bwpgBuilder.build()).build();
}
MefServices mefServices = DefaultMefServices.builder().profiles(profilesBuilder.build()).build();
MseaUniEvcService.MseaUniEvcServiceBuilder evcUniBuilder =
new MseaUniEvcServiceOpParam.MseaUniEvcServiceBuilder();
MseaUniEvcServiceOpParam mseaUniEvcServiceFilter =
(MseaUniEvcServiceOpParam) evcUniBuilder.mefServices(mefServices).build();
NetconfSession session = controller.getDevicesMap().get(deviceId).getSession();
try {
mseaUniEvcServiceSvc.setMseaUniEvcService(mseaUniEvcServiceFilter, session, TargetConfig.RUNNING);
} catch (NetconfException e) {
//This can fail if the BWP Group is deleted before the EVC that is dependent on it
//The delete of the EVC will be called on a separate thread to that should proceed
//within a few seconds after which we should try again
AtomicInteger retry = new AtomicInteger(4);
if (meterOp.type() == MeterOperation.Type.REMOVE &&
e.getMessage().startsWith("Failed to run edit-config through NETCONF")) {
while (retry.getAndDecrement() > 0) {
try {
Thread.sleep(1000L);
log.debug("Retrying deletion of Bandwith Profile Group {}", String.valueOf(meterId));
mseaUniEvcServiceSvc.setMseaUniEvcService(mseaUniEvcServiceFilter,
session, TargetConfig.RUNNING);
return; //If it did not throw an exception
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (NetconfException e1) {
log.debug("NETCONF failed to delete profile - trying again in 1 sec");
e1.printStackTrace();
}
}
log.error("Error deleting BWPGroup {} from {} after 4 tries: {}", meterId, deviceId, e.getMessage());
} else {
log.error("Error adding BWPGroup {} from {}: {}", meterId, deviceId, e.getMessage());
throw new UnsupportedOperationException(e);
}
e.printStackTrace();
}
}
private static long toBitsPerSec(long rate, Unit unit) {
if (unit == Unit.KB_PER_SEC) {
return rate * 8;
} else {
return -1;
}
}
}