blob: 03405d7215c648109d24cb76fe2b1e6a463c9487 [file] [log] [blame]
Sean Condon06613e92017-06-09 15:14:01 +01001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Sean Condon06613e92017-06-09 15:14:01 +01003 *
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.drivers.microsemi;
18
19
20import static org.slf4j.LoggerFactory.getLogger;
21
22import java.util.concurrent.atomic.AtomicInteger;
23
24import org.apache.felix.scr.annotations.Activate;
25import org.apache.felix.scr.annotations.Component;
26import org.apache.felix.scr.annotations.Deactivate;
27import org.apache.felix.scr.annotations.Reference;
28import org.apache.felix.scr.annotations.ReferenceCardinality;
29import org.onosproject.core.CoreService;
30import org.onosproject.drivers.microsemi.yang.MseaUniEvcServiceNetconfService;
31import org.onosproject.net.DeviceId;
32import org.onosproject.net.meter.Band;
33import org.onosproject.net.meter.Meter.Unit;
34import org.onosproject.net.meter.MeterOperation;
35import org.onosproject.net.meter.MeterOperations;
36import org.onosproject.net.meter.MeterProvider;
37import org.onosproject.net.meter.MeterProviderRegistry;
38import org.onosproject.net.meter.MeterProviderService;
39import org.onosproject.net.provider.AbstractProvider;
40import org.onosproject.net.provider.ProviderId;
41import org.onosproject.netconf.DatastoreId;
42import org.onosproject.netconf.NetconfController;
43import org.onosproject.netconf.NetconfException;
44import org.onosproject.netconf.NetconfSession;
45import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.CosColorType;
46import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.PriorityType;
47import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.coscolortype.CosColorTypeEnum;
48import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.MseaUniEvcServiceOpParam;
49import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.DefaultMefServices;
50import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.MefServices;
51import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.DefaultProfiles;
52import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.Profiles;
53import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.BwpGroup;
54import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.Cos;
55import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.DefaultBwpGroup;
56import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.DefaultCos;
57import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.bwpgroup.Bwp;
58import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.bwpgroup.DefaultBwp;
59import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.DefaultEvcCosTypeEvcColorId;
60import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.EvcCosTypeEvcColorId;
61import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.evccostypeevccolorid.DefaultEvcCosTypeAll8PrioTo1EvcColor;
62import org.onosproject.yang.gen.v1.mseaunievcservice.rev20160317.mseaunievcservice.mefservices.profiles.cos.costypechoice.evccostypeevccolorid.EvcCosTypeAll8PrioTo1EvcColor;
63import org.slf4j.Logger;
64
65/**
66 * Provider which uses an NETCONF controller to handle meters.
67 *
68 * TODO: move this to an architecture similar to FlowRuleDriverProvider in order
69 * to use a behavior to discover meters.
70 */
71@Component(immediate = true, enabled = true)
72public class EA1000MeterProvider extends AbstractProvider implements MeterProvider {
73
74 private final Logger log = getLogger(getClass());
75
76 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected NetconfController controller;
78
79 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 protected MeterProviderRegistry providerRegistry;
81
82 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 protected CoreService coreService;
84
85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 protected MseaUniEvcServiceNetconfService mseaUniEvcServiceSvc;
87
88 private MeterProviderService providerService;
89
90 private static final int COS_INDEX_1 = 1;
91 private static final short DEFAULT_OUTGOING_PRIO = 3;
92
93 /**
94 * Creates a OpenFlow meter provider.
95 */
96 public EA1000MeterProvider() {
97 super(new ProviderId("netconf", "org.onosproject.provider.meter.microsemi"));
98 }
99
100 @Activate
101 public void activate() {
102 providerService = providerRegistry.register(this);
103
104 }
105
106 @Deactivate
107 public void deactivate() {
108 providerRegistry.unregister(this);
109
110 providerService = null;
111 }
112
113 @Override
114 public void performMeterOperation(DeviceId deviceId, MeterOperations meterOps) {
115 log.debug("Adding meterOps to Microsemi Meter Store");
116 }
117
118 @Override
119 public void performMeterOperation(DeviceId deviceId, MeterOperation meterOp) {
120 if (meterOp == null || deviceId == null) {
121 log.warn("Missing argument for performMeterOperation()");
122 return;
123 }
124 log.debug("{} meterOp {} to Microsemi Meter Store", meterOp.type(), meterOp);
125
126 long meterId = meterOp.meter().id().id();
127 String deviceName = deviceId.uri().getSchemeSpecificPart();
128 Unit unit = meterOp.meter().unit();
129
130 Profiles profiles = new DefaultProfiles();
131 if (meterOp.type() == MeterOperation.Type.ADD || meterOp.type() == MeterOperation.Type.MODIFY) {
132 Bwp bwp = new DefaultBwp();
133 bwp.cosIndex(COS_INDEX_1);
134 bwp.name("BWP-" + String.valueOf(meterId) + "-" + deviceName);
135
136 long cirRateKbps = 0L;
137 long cbsRateKbps = 0L;
138 long eirRateKbps = 0L;
139 long ebsRateKbps = 0L;
140 for (Band band:meterOp.meter().bands()) {
141 if (band.type() == Band.Type.REMARK) {
142 //This relates to CIR/CBS
143 cirRateKbps = toBitsPerSec(band.rate(), unit);
144 cbsRateKbps = band.burst(); //Already in kbps
145 } else if (band.type() == Band.Type.DROP) {
146 //This relates to EIR/EBS
147 eirRateKbps = toBitsPerSec(band.rate(), unit);
148 ebsRateKbps = band.burst(); //Already in kbps
149 }
150 }
151 bwp.committedInformationRate(cirRateKbps);
152 bwp.excessInformationRate(eirRateKbps - cirRateKbps);
153 if (meterOp.meter().isBurst()) {
154 bwp.committedBurstSize(cbsRateKbps);
155 bwp.excessBurstSize(ebsRateKbps - cbsRateKbps);
156 }
157
158 BwpGroup bwpg = new DefaultBwpGroup();
159 bwpg.groupIndex((short) meterId);
160 bwpg.addToBwp(bwp);
161
162 //Create cos-1 as referenced above - we only support 1 at the moment
163 Cos cos = new DefaultCos();
164 cos.cosIndex(COS_INDEX_1);
165 cos.name("COS-1");
166 cos.outgoingCosValue(PriorityType.of(DEFAULT_OUTGOING_PRIO));
167 cos.colorAware(true);
168 cos.colorForward(true);
169
170 EvcCosTypeAll8PrioTo1EvcColor ect =
171 new DefaultEvcCosTypeAll8PrioTo1EvcColor();
172 ect.evcAll8ColorTo(CosColorType.of(CosColorTypeEnum.GREEN));
173 profiles.addToBwpGroup(bwpg);
174
175 EvcCosTypeEvcColorId cid = new DefaultEvcCosTypeEvcColorId();
176 cid.evcCosTypeAll8PrioTo1EvcColor(ect);
177 cos.cosTypeChoice(cid);
178 profiles.addToCos(cos);
179 } else if (meterOp.type() == MeterOperation.Type.REMOVE) {
180 BwpGroup bwpg = new DefaultBwpGroup();
181 bwpg.groupIndex((short) meterId);
182
183 profiles.addToBwpGroup(bwpg);
184 }
185
186 MefServices mefServices = new DefaultMefServices();
187 mefServices.profiles(profiles);
188
189 MseaUniEvcServiceOpParam mseaUniEvcServiceFilter = new MseaUniEvcServiceOpParam();
190 mseaUniEvcServiceFilter.mefServices(mefServices);
191
192 NetconfSession session = controller.getDevicesMap().get(deviceId).getSession();
193 try {
194 if (meterOp.type() == MeterOperation.Type.REMOVE) {
195 mseaUniEvcServiceSvc.deleteMseaUniEvcService(mseaUniEvcServiceFilter,
196 session, DatastoreId.RUNNING);
197 } else {
198 mseaUniEvcServiceSvc.setMseaUniEvcService(mseaUniEvcServiceFilter,
199 session, DatastoreId.RUNNING);
200 }
201 } catch (NetconfException e) {
202 //This can fail if the BWP Group is deleted before the EVC that is dependent on it
203 //The delete of the EVC will be called on a separate thread to that should proceed
204 //within a few seconds after which we should try again
205 AtomicInteger retry = new AtomicInteger(4);
206 if (meterOp.type() == MeterOperation.Type.REMOVE &&
207 e.getMessage().startsWith("Failed to run edit-config through NETCONF")) {
208 while (retry.getAndDecrement() > 0) {
209 try {
210 Thread.sleep(1000L);
211 log.debug("Retrying deletion of Bandwith Profile Group {}",
212 String.valueOf(meterId));
213 mseaUniEvcServiceSvc.setMseaUniEvcService(mseaUniEvcServiceFilter,
214 session, DatastoreId.RUNNING);
215 return; //If it did not throw an exception
216 } catch (InterruptedException e1) {
Ray Milkey5c7d4882018-02-05 14:50:39 -0800217 Thread.currentThread().interrupt();
Sean Condon06613e92017-06-09 15:14:01 +0100218 log.debug("Error when deleting BWP profile on EA1000" +
219 " - trying again in 1 sec", e1);
220 } catch (NetconfException e1) {
221 log.debug("NETCONF failed to delete profile - trying again in 1 sec", e1);
222 }
223 }
224 log.error("Error deleting BWPGroup {} from {} after 4 tries: {}",
225 meterId, deviceId, e.getMessage());
226 } else {
227 log.error("Error adding BWPGroup {} from {}: {}",
228 meterId, deviceId, e.getMessage());
229 throw new UnsupportedOperationException(e);
230 }
231 }
232 }
233
234 private static long toBitsPerSec(long rate, Unit unit) {
235 if (unit == Unit.KB_PER_SEC) {
236 return rate * 8;
237 } else {
238 return -1;
239 }
240 }
241}