Add support for 200G with 31.6 Gbaud
[transportpce.git] / renderer / src / main / java / org / opendaylight / transportpce / renderer / openroadminterface / OpenRoadmInterface710.java
1 /*
2  * Copyright © 2021 AT&T and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8
9 package org.opendaylight.transportpce.renderer.openroadminterface;
10
11 import java.math.BigDecimal;
12 import java.util.ArrayList;
13 import java.util.Arrays;
14 import java.util.List;
15 import java.util.Optional;
16 import java.util.stream.IntStream;
17 import org.opendaylight.transportpce.common.StringConstants;
18 import org.opendaylight.transportpce.common.fixedflex.GridConstant;
19 import org.opendaylight.transportpce.common.fixedflex.SpectrumInformation;
20 import org.opendaylight.transportpce.common.mapping.PortMapping;
21 import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaceException;
22 import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaces;
23 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.az.api.info.AEndApiInfo;
24 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.az.api.info.ZEndApiInfo;
25 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev220114.mapping.Mapping;
26 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.attributes.rev200327.TrailTraceOther.TimDetectMode;
27 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.attributes.rev200327.parent.odu.allocation.ParentOduAllocationBuilder;
28 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.attributes.rev200327.parent.odu.allocation.parent.odu.allocation.trib.slots.choice.OpucnBuilder;
29 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.link.types.rev191129.PowerDBm;
30 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.Foic24;
31 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.Foic28;
32 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.Foic36;
33 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.Foic48;
34 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.FrequencyTHz;
35 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.ModulationFormat;
36 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.ProvisionModeType;
37 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.R200GOtsi;
38 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.R300GOtsi;
39 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.R400GOtsi;
40 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev200529.Ofec;
41 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev200529.Rsfec;
42 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.interfaces.grp.InterfaceBuilder;
43 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.interfaces.grp.InterfaceKey;
44 import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev191129.AdminStates;
45 import org.opendaylight.yang.gen.v1.http.org.openroadm.ethernet.interfaces.rev200529.Interface1Builder;
46 import org.opendaylight.yang.gen.v1.http.org.openroadm.ethernet.interfaces.rev200529.ethernet.container.EthernetBuilder;
47 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev191129.EthernetCsmacd;
48 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev191129.InterfaceType;
49 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev191129.OtnOdu;
50 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev191129.OtnOtu;
51 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev191129.Otsi;
52 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev191129.OtsiGroup;
53 import org.opendaylight.yang.gen.v1.http.org.openroadm.maintenance.loopback.rev191129.maint.loopback.MaintLoopbackBuilder;
54 import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.tributary.signal.interfaces.rev200529.otsi.attributes.FlexoBuilder;
55 import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.tributary.signal.interfaces.rev200529.otsi.container.OtsiBuilder;
56 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.ODUCn;
57 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.ODUTTP;
58 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.ODUTTPCTP;
59 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.ODUflexCbr;
60 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.ODUflexCbr400G;
61 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.OTUCn;
62 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.OpucnTribSlotDef;
63 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.PayloadTypeDef;
64 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.OduAttributes.MonitoringMode;
65 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.odu.container.OduBuilder;
66 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.opu.OpuBuilder;
67 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.otu.interfaces.rev200529.otu.container.OtuBuilder;
68 import org.opendaylight.yang.gen.v1.http.org.openroadm.otsi.group.interfaces.rev200529.otsi.group.container.OtsiGroupBuilder;
69 import org.opendaylight.yangtools.yang.common.Uint16;
70 import org.opendaylight.yangtools.yang.common.Uint32;
71 import org.opendaylight.yangtools.yang.common.Uint8;
72 import org.slf4j.Logger;
73 import org.slf4j.LoggerFactory;
74
75 public class OpenRoadmInterface710 {
76     private static final String MAPPING_ERROR_EXCEPTION_MESSAGE =
77         "Unable to get mapping from PortMapping for node % and logical connection port %s";
78     private static final String MODULATION_FMT_EXCEPTION_MESSAGE =
79         "Unable to get the modulation format";
80     private static final String RATE_EXCEPTION_MESSAGE =
81         "Unable to get the rate";
82     private static final String ODUC = "-ODUC";
83     private static final List<String> SUPPORTED_ODUCN_RATES = new ArrayList<>() {
84         {
85             add("2");
86             add("3");
87             add("4");
88         }
89     };
90     private final PortMapping portMapping;
91     private final OpenRoadmInterfaces openRoadmInterfaces;
92     private static final Logger LOG = LoggerFactory.getLogger(OpenRoadmInterface710.class);
93
94     public OpenRoadmInterface710(PortMapping portMapping, OpenRoadmInterfaces openRoadmInterfaces) {
95         this.portMapping = portMapping;
96         this.openRoadmInterfaces = openRoadmInterfaces;
97     }
98
99     public String createOpenRoadmEthInterface(String nodeId, String logicalConnPoint)
100             throws OpenRoadmInterfaceException {
101         Mapping portMap = portMapping.getMapping(nodeId, logicalConnPoint);
102         if (portMap == null) {
103             throw new OpenRoadmInterfaceException(
104                 String.format(MAPPING_ERROR_EXCEPTION_MESSAGE, nodeId, logicalConnPoint));
105         }
106
107         // Ethernet interface specific data
108         EthernetBuilder ethIfBuilder = new EthernetBuilder()
109             .setFec(Rsfec.class)
110             .setSpeed(Uint32.valueOf(400000));
111
112         InterfaceBuilder ethInterfaceBldr = createGenericInterfaceBuilder(portMap, EthernetCsmacd.class,
113             logicalConnPoint + "-ETHERNET");
114         // Create Interface1 type object required for adding as augmentation
115         Interface1Builder ethIf1Builder = new Interface1Builder();
116         ethInterfaceBldr.addAugmentation(ethIf1Builder.setEthernet(ethIfBuilder.build()).build());
117
118         // Post interface on the device
119         openRoadmInterfaces.postInterface(nodeId, ethInterfaceBldr);
120
121         // Post the equipment-state change on the device circuit-pack
122         openRoadmInterfaces.postEquipmentState(nodeId, portMap.getSupportingCircuitPackName(), true);
123
124         return ethInterfaceBldr.getName();
125     }
126
127
128     public String createOpenRoadmOtsiInterface(String nodeId, String logicalConnPoint,
129             SpectrumInformation spectrumInformation)
130             throws OpenRoadmInterfaceException {
131
132         ModulationFormat modulationFormat;
133         Optional<ModulationFormat> optionalModulationFormat = ModulationFormat
134             .forName(spectrumInformation.getModulationFormat());
135         if (optionalModulationFormat.isPresent()) {
136             modulationFormat =  optionalModulationFormat.get();
137         } else {
138             throw new OpenRoadmInterfaceException(
139                 String.format(MODULATION_FMT_EXCEPTION_MESSAGE));
140         }
141
142         // OTSI interface specific data
143         OtsiBuilder  otsiBuilder = new OtsiBuilder()
144             .setFrequency(new FrequencyTHz(spectrumInformation.getCenterFrequency()))
145             .setTransmitPower(new PowerDBm(new BigDecimal("-5")))
146             .setProvisionMode(ProvisionModeType.Explicit)
147             .setFec(Ofec.class)
148             .setModulationFormat(modulationFormat);
149
150         // Set the Flexo values
151         FlexoBuilder flexoBuilder = new FlexoBuilder();
152         boolean rateNotFound = false;
153         // Use the rate to switch rather than modulation format
154         int serviceRate = getServiceRate(modulationFormat, spectrumInformation);
155         switch (serviceRate) {
156             case 200:
157                 LOG.info("Given modulation format is {} and thus rate is 200G", modulationFormat);
158                 if (modulationFormat == ModulationFormat.DpQam16) {
159                     LOG.info("FOIC is 2.8 for 31.6 Gbaud and rate is 200");
160                     // FOIC rate is different
161                     flexoBuilder.setFoicType(Foic28.class)
162                         .setIid(new ArrayList<>(Arrays.asList(Uint8.valueOf(1), Uint8.valueOf(2),
163                             Uint8.valueOf(3), Uint8.valueOf(4))));
164                 } else {
165                     // default is dp-qpsk for 200G under 63.1 GBaud
166                     flexoBuilder.setFoicType(Foic24.class)
167                         .setIid(new ArrayList<>(Arrays.asList(Uint8.valueOf(1), Uint8.valueOf(2))));
168                 }
169                 otsiBuilder.setOtsiRate(R200GOtsi.class)
170                     .setFlexo(flexoBuilder.build());
171                 break;
172             case 300:
173                 LOG.info("Given modulation format is {} and thus rate is 300G", modulationFormat);
174                 flexoBuilder.setFoicType(Foic36.class)
175                     .setIid(new ArrayList<>(Arrays.asList(Uint8.valueOf(1), Uint8.valueOf(2),
176                         Uint8.valueOf(3))));
177                 otsiBuilder.setOtsiRate(R300GOtsi.class)
178                     .setFlexo(flexoBuilder.build());
179                 break;
180             case 400:
181                 // Default baud-rate is 63.1 Gbaud
182                 LOG.info("Given modulation format is {} and thus rate is 400G", modulationFormat);
183                 flexoBuilder.setFoicType(Foic48.class)
184                     .setIid(new ArrayList<>(Arrays.asList(Uint8.valueOf(1), Uint8.valueOf(2),
185                         Uint8.valueOf(3), Uint8.valueOf(4))));
186                 otsiBuilder.setModulationFormat(modulationFormat)
187                     .setOtsiRate(R400GOtsi.class)
188                     .setFlexo(flexoBuilder.build());
189                 break;
190             default:
191                 LOG.error("Rate {} is unsupported", serviceRate);
192                 rateNotFound = true;
193                 break;
194         }
195
196         if (rateNotFound) {
197             throw new OpenRoadmInterfaceException(
198                 String.format(RATE_EXCEPTION_MESSAGE));
199         }
200
201         Mapping portMap = portMapping.getMapping(nodeId, logicalConnPoint);
202         if (portMap == null) {
203             throw new OpenRoadmInterfaceException(
204                 String.format(MAPPING_ERROR_EXCEPTION_MESSAGE, nodeId, logicalConnPoint));
205         }
206         // Create generic interface
207         InterfaceBuilder otsiInterfaceBldr = createGenericInterfaceBuilder(portMap, Otsi.class,
208             spectrumInformation.getIdentifierFromParams(logicalConnPoint));
209         // Create Interface1 type object required for adding as augmentation
210         org.opendaylight.yang.gen.v1.http
211             .org.openroadm.optical.channel.tributary.signal.interfaces.rev200529.Interface1Builder otsiIf1Builder =
212             new org.opendaylight.yang.gen.v1.http
213                 .org.openroadm.optical.channel.tributary.signal.interfaces.rev200529.Interface1Builder();
214
215         otsiInterfaceBldr.addAugmentation(otsiIf1Builder.setOtsi(otsiBuilder.build()).build());
216
217         // Post interface on the device
218         openRoadmInterfaces.postInterface(nodeId, otsiInterfaceBldr);
219
220         // Post the equipment-state change on the device circuit-pack if xpdr node
221         if (portMap.getLogicalConnectionPoint().contains(StringConstants.NETWORK_TOKEN)) {
222             this.openRoadmInterfaces.postEquipmentState(nodeId, portMap.getSupportingCircuitPackName(), true);
223         }
224
225         return otsiInterfaceBldr.getName();
226     }
227
228     // This is a transponder use-case where the supporting port is just one, but YANG model
229     // requires supporting port to be list
230     public String createOpenRoadmOtsiGroupInterface(String nodeId, String logicalConnPoint,
231             String supportingOtsiInterface, SpectrumInformation spectrumInformation)
232             throws OpenRoadmInterfaceException {
233         Mapping portMap = portMapping.getMapping(nodeId, logicalConnPoint);
234         if (portMap == null) {
235             throw new OpenRoadmInterfaceException(
236                 String.format(MAPPING_ERROR_EXCEPTION_MESSAGE,
237                     nodeId, logicalConnPoint));
238         }
239         // Check the modulation format
240         ModulationFormat modulationFormat;
241         Optional<ModulationFormat> optionalModulationFormat = ModulationFormat
242             .forName(spectrumInformation.getModulationFormat());
243         if (optionalModulationFormat.isPresent()) {
244             modulationFormat =  optionalModulationFormat.get();
245         } else {
246             throw new OpenRoadmInterfaceException(
247                 String.format(MODULATION_FMT_EXCEPTION_MESSAGE));
248         }
249         int serviceRate = getServiceRate(modulationFormat, spectrumInformation);
250         // Create an OTSI group object
251         OtsiGroupBuilder otsiGroupBuilder = new OtsiGroupBuilder()
252             .setGroupId(Uint32.valueOf(1));
253         boolean rateNotFound = false;
254         switch (serviceRate) {
255             case 200:
256                 otsiGroupBuilder.setGroupRate(R200GOtsi.class);
257                 break;
258             case 300:
259                 otsiGroupBuilder.setGroupRate(R300GOtsi.class);
260                 break;
261             case 400:
262                 otsiGroupBuilder.setGroupRate(R400GOtsi.class);
263                 break;
264             default:
265                 LOG.error("Rate {} is not supported", serviceRate);
266                 rateNotFound = true;
267                 break;
268         }
269         if (rateNotFound) {
270             throw new OpenRoadmInterfaceException(
271                 String.format(RATE_EXCEPTION_MESSAGE));
272         }
273
274         // Create generic interface
275         InterfaceBuilder otsiGroupInterfaceBldr = createGenericInterfaceBuilder(portMap, OtsiGroup.class,
276             logicalConnPoint + String.join("-", "", "OTSIGROUP", serviceRate + "G"));
277
278         // Create a list
279         List<String> listSupportingOtsiInterface = new ArrayList<>();
280         listSupportingOtsiInterface.add(supportingOtsiInterface);
281         otsiGroupInterfaceBldr.setSupportingInterfaceList(listSupportingOtsiInterface);
282
283         org.opendaylight.yang.gen.v1.http.org.openroadm.otsi.group.interfaces.rev200529.Interface1Builder
284             otsiGroupIf1Builder =
285             new org.opendaylight.yang.gen.v1.http.org.openroadm.otsi.group.interfaces.rev200529.Interface1Builder();
286         otsiGroupInterfaceBldr.addAugmentation(otsiGroupIf1Builder.setOtsiGroup(otsiGroupBuilder.build()).build());
287
288         // Post interface on the device
289         openRoadmInterfaces.postInterface(nodeId, otsiGroupInterfaceBldr);
290
291         // Post the equipment-state change on the device circuit-pack if xpdr node
292         if (portMap.getLogicalConnectionPoint().contains(StringConstants.NETWORK_TOKEN)) {
293             this.openRoadmInterfaces.postEquipmentState(nodeId, portMap.getSupportingCircuitPackName(), true);
294         }
295
296         return otsiGroupInterfaceBldr.getName();
297     }
298
299     public String createOpenRoadmOtucnInterface(String nodeId, String logicalConnPoint,
300             String supportingOtsiGroupInterface, AEndApiInfo apiInfoA, ZEndApiInfo apiInfoZ)
301             throws OpenRoadmInterfaceException {
302         Mapping mapping = portMapping.getMapping(nodeId, logicalConnPoint);
303         if (mapping == null) {
304             throw new OpenRoadmInterfaceException(
305                 String.format(MAPPING_ERROR_EXCEPTION_MESSAGE,
306                     nodeId, logicalConnPoint));
307         }
308         // Create an OTUCn object
309         MaintLoopbackBuilder maintLoopbackBuilder = new MaintLoopbackBuilder();
310         maintLoopbackBuilder.setEnabled(false);
311         OtuBuilder otuBuilder = new OtuBuilder()
312             .setRate(OTUCn.class)
313             .setTimActEnabled(false)
314             .setTimDetectMode(TimDetectMode.Disabled)
315             .setDegmIntervals(Uint8.valueOf(2))
316             .setDegthrPercentage(Uint16.valueOf(100))
317             .setMaintLoopback(maintLoopbackBuilder.build());
318         if (apiInfoA != null) {
319             otuBuilder.setTxSapi(apiInfoA.getSapi())
320                 .setTxDapi(apiInfoA.getDapi())
321                 .setExpectedSapi(apiInfoA.getExpectedSapi())
322                 .setExpectedDapi(apiInfoA.getExpectedDapi());
323         }
324         if (apiInfoZ != null) {
325             otuBuilder.setTxSapi(apiInfoZ.getSapi())
326                 .setTxDapi(apiInfoZ.getDapi())
327                 .setExpectedSapi(apiInfoZ.getExpectedSapi())
328                 .setExpectedDapi(apiInfoZ.getExpectedDapi());
329         }
330         // Set the OTUCn rate for various rates
331         String rate = supportingOtsiGroupInterface.substring(supportingOtsiGroupInterface.lastIndexOf('-') + 1);
332
333         String otucnrate = null;
334         boolean rateNotFound = false;
335         switch (rate) {
336             case "200G":
337                 otuBuilder.setOtucnNRate(Uint16.valueOf(2));
338                 otucnrate = "2";
339                 break;
340             case "300G":
341                 otuBuilder.setOtucnNRate(Uint16.valueOf(3));
342                 otucnrate = "3";
343                 break;
344             case "400G":
345                 otuBuilder.setOtucnNRate(Uint16.valueOf(4));
346                 otucnrate = "4";
347                 break;
348             default:
349                 LOG.error("Rate {} is not supported", rate);
350                 rateNotFound = true;
351                 break;
352         }
353         if (rateNotFound) {
354             throw new OpenRoadmInterfaceException(
355                 String.format(RATE_EXCEPTION_MESSAGE));
356         }
357
358         InterfaceBuilder otuInterfaceBuilder = createGenericInterfaceBuilder(mapping, OtnOtu.class,
359             logicalConnPoint + "-OTUC" + otucnrate);
360
361         // Create a list
362         List<String> listSupportingOtsiGroupInterface = new ArrayList<>();
363         listSupportingOtsiGroupInterface.add(supportingOtsiGroupInterface);
364
365         otuInterfaceBuilder.setSupportingInterfaceList(listSupportingOtsiGroupInterface);
366         org.opendaylight.yang.gen.v1.http.org.openroadm.otn.otu.interfaces.rev200529.Interface1Builder otuIf1Builder =
367             new org.opendaylight.yang.gen.v1.http.org.openroadm.otn.otu.interfaces.rev200529.Interface1Builder();
368
369         otuInterfaceBuilder.addAugmentation(otuIf1Builder.setOtu(otuBuilder.build()).build());
370
371         // Post interface on the device
372         openRoadmInterfaces.postInterface(nodeId, otuInterfaceBuilder);
373         // Post the equipment-state change on the device circuit-pack if xpdr node
374         if (mapping.getLogicalConnectionPoint().contains(StringConstants.NETWORK_TOKEN)) {
375             this.openRoadmInterfaces.postEquipmentState(nodeId, mapping.getSupportingCircuitPackName(), true);
376         }
377         this.portMapping.updateMapping(nodeId, mapping);
378         return otuInterfaceBuilder.getName();
379     }
380
381     public String createOpenRoadmOducnInterface(String nodeId, String logicalConnPoint)
382             throws OpenRoadmInterfaceException {
383         Mapping mapping = portMapping.getMapping(nodeId, logicalConnPoint);
384         if (mapping == null) {
385             throw new OpenRoadmInterfaceException(
386                 String.format(MAPPING_ERROR_EXCEPTION_MESSAGE,
387                     nodeId, logicalConnPoint));
388         }
389         // Create ODUcn object
390         // Start with OPU object
391         // OPU payload
392         OpuBuilder opuBuilder = new OpuBuilder()
393             .setExpPayloadType(PayloadTypeDef.getDefaultInstance("22"))
394             .setPayloadType(PayloadTypeDef.getDefaultInstance("22"));
395
396         // Create an ODUCn object
397         OduBuilder oduBuilder = new OduBuilder()
398             .setRate(ODUCn.class)
399             .setOduFunction(ODUTTP.class)
400             .setMonitoringMode(MonitoringMode.Terminated)
401             .setTimActEnabled(false)
402             .setTimDetectMode(TimDetectMode.Disabled)
403             .setDegmIntervals(Uint8.valueOf(2))
404             .setDegthrPercentage(Uint16.valueOf(100))
405             .setOducnNRate(Uint16.valueOf(4))
406             .setOpu(opuBuilder.build());
407
408         // Create a list
409         String supportingOtucn;
410         List<String> listSupportingOtucnInterface = new ArrayList<>();
411         if (mapping.getSupportingOtucn() != null) {
412             listSupportingOtucnInterface.add(mapping.getSupportingOtucn());
413             supportingOtucn = mapping.getSupportingOtucn();
414         } else {
415             throw new OpenRoadmInterfaceException(
416                 String.format("Missing supporting OTUCn interface on port-mapping"));
417         }
418
419         // Set the ODUCn rate from OTUCn interface naming convention
420         String oducnrate = supportingOtucn.substring(supportingOtucn.length() - 1);
421         // check if the oducnrate is a valid value and if it is invalid, then throw error
422         if (!SUPPORTED_ODUCN_RATES.contains(oducnrate)) {
423             throw new OpenRoadmInterfaceException(
424                 String.format(RATE_EXCEPTION_MESSAGE));
425         }
426
427         oduBuilder.setOducnNRate(Uint16.valueOf(oducnrate));
428
429         InterfaceBuilder oduInterfaceBuilder = createGenericInterfaceBuilder(mapping, OtnOdu.class,
430             logicalConnPoint + "-ODUC" + oducnrate);
431
432         oduInterfaceBuilder.setSupportingInterfaceList(listSupportingOtucnInterface);
433         org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.Interface1Builder oduIf1Builder =
434             new org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.Interface1Builder();
435
436         oduInterfaceBuilder.addAugmentation(oduIf1Builder.setOdu(oduBuilder.build()).build());
437
438         // Post interface on the device
439         openRoadmInterfaces.postInterface(nodeId, oduInterfaceBuilder);
440
441         // Post the equipment-state change on the device circuit-pack if xpdr node
442         if (mapping.getLogicalConnectionPoint().contains(StringConstants.NETWORK_TOKEN)) {
443             this.openRoadmInterfaces.postEquipmentState(nodeId, mapping.getSupportingCircuitPackName(), true);
444         }
445
446         return oduInterfaceBuilder.getName();
447     }
448
449     // With SAPI and DAPI information
450     public String createOpenRoadmOducnInterface(String anodeId, String alogicalConnPoint,
451             String supportingOtucn, String znodeId, String zlogicalConnPoint)
452             throws OpenRoadmInterfaceException {
453         Mapping portMapA = portMapping.getMapping(anodeId, alogicalConnPoint);
454         Mapping portMapZ = portMapping.getMapping(znodeId, zlogicalConnPoint);
455         if (portMapA == null) {
456             throw new OpenRoadmInterfaceException(
457                 String.format(MAPPING_ERROR_EXCEPTION_MESSAGE,
458                     anodeId, alogicalConnPoint));
459         }
460         // On the Zside
461         if (portMapZ == null) {
462             throw new OpenRoadmInterfaceException(
463                 String.format(MAPPING_ERROR_EXCEPTION_MESSAGE,
464                     znodeId, zlogicalConnPoint));
465
466         }
467         // Create ODUcn object
468         // Start with OPU object
469         // OPU payload
470         OpuBuilder opuBuilder = new OpuBuilder()
471             .setExpPayloadType(PayloadTypeDef.getDefaultInstance("22"))
472             .setPayloadType(PayloadTypeDef.getDefaultInstance("22"));
473
474         // Create an ODUC4 object
475         OduBuilder oduBuilder = new OduBuilder()
476             .setRate(ODUCn.class)
477             .setOduFunction(ODUTTP.class)
478             .setMonitoringMode(MonitoringMode.Terminated)
479             .setTimActEnabled(false)
480             .setTimDetectMode(TimDetectMode.Disabled)
481             .setDegmIntervals(Uint8.valueOf(2))
482             .setDegthrPercentage(Uint16.valueOf(100))
483             .setOpu(opuBuilder.build())
484             .setTxSapi(portMapA.getLcpHashVal())
485             .setTxDapi(portMapZ.getLcpHashVal())
486             .setExpectedSapi(portMapZ.getLcpHashVal())
487             .setExpectedDapi(portMapZ.getLcpHashVal());
488
489         // Set the ODUCn rate from OTUCn interface naming convention
490         String oducnrate = supportingOtucn.substring(supportingOtucn.length() - 1);
491
492         // check if the oducnrate is a valid value and if it is invalid, then throw error
493         if (!SUPPORTED_ODUCN_RATES.contains(oducnrate)) {
494             throw new OpenRoadmInterfaceException(
495                 String.format(RATE_EXCEPTION_MESSAGE));
496         }
497
498         oduBuilder.setOducnNRate(Uint16.valueOf(oducnrate));
499
500         InterfaceBuilder oduInterfaceBuilder = createGenericInterfaceBuilder(portMapA, OtnOdu.class,
501             alogicalConnPoint + ODUC + oducnrate);
502
503         // Create a list
504         List<String> listSupportingOtucnInterface = new ArrayList<>();
505         listSupportingOtucnInterface.add(supportingOtucn);
506
507         oduInterfaceBuilder.setSupportingInterfaceList(listSupportingOtucnInterface);
508         org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.Interface1Builder oduIf1Builder =
509             new org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.Interface1Builder();
510
511         oduInterfaceBuilder.addAugmentation(oduIf1Builder.setOdu(oduBuilder.build()).build());
512
513         // Post interface on the device
514         openRoadmInterfaces.postInterface(anodeId, oduInterfaceBuilder);
515
516         // Post the equipment-state change on the device circuit-pack if xpdr node
517         if (portMapA.getLogicalConnectionPoint().contains(StringConstants.NETWORK_TOKEN)) {
518             this.openRoadmInterfaces.postEquipmentState(anodeId, portMapA.getSupportingCircuitPackName(), true);
519         }
520
521         return oduInterfaceBuilder.getName();
522     }
523
524     public String createOpenRoadmOtnOducnInterface(String nodeId, String logicalConnPoint,
525         String supportingOtucn)
526         throws OpenRoadmInterfaceException {
527         Mapping portMap = portMapping.getMapping(nodeId, logicalConnPoint);
528         if (portMap == null) {
529             throw new OpenRoadmInterfaceException(
530                 String.format(MAPPING_ERROR_EXCEPTION_MESSAGE,
531                     nodeId, logicalConnPoint));
532         }
533         // Create ODUcn object
534         // Start with OPU object
535         // OPU payload
536         OpuBuilder opuBuilder = new OpuBuilder()
537             .setExpPayloadType(PayloadTypeDef.getDefaultInstance("22"))
538             .setPayloadType(PayloadTypeDef.getDefaultInstance("22"));
539
540         // Create an ODUC4 object
541         OduBuilder oduBuilder = new OduBuilder()
542             .setRate(ODUCn.class)
543             .setOduFunction(ODUTTP.class)
544             .setMonitoringMode(MonitoringMode.Terminated)
545             .setTimActEnabled(false)
546             .setTimDetectMode(TimDetectMode.Disabled)
547             .setDegmIntervals(Uint8.valueOf(2))
548             .setDegthrPercentage(Uint16.valueOf(100))
549             .setOpu(opuBuilder.build());
550
551         // Set the ODUCn rate from OTUCn interface naming convention
552         String oducnrate = supportingOtucn.substring(supportingOtucn.length() - 1);
553
554         // check if the oducnrate is a valid value and if it is invalid, then throw error
555         if (!SUPPORTED_ODUCN_RATES.contains(oducnrate)) {
556             throw new OpenRoadmInterfaceException(
557                 String.format(RATE_EXCEPTION_MESSAGE));
558         }
559
560         oduBuilder.setOducnNRate(Uint16.valueOf(oducnrate));
561
562         InterfaceBuilder oduInterfaceBuilder = createGenericInterfaceBuilder(portMap, OtnOdu.class,
563             logicalConnPoint + ODUC + oducnrate);
564
565         // Create a list
566         List<String> listSupportingOtucnInterface = new ArrayList<>();
567         listSupportingOtucnInterface.add(supportingOtucn);
568
569         oduInterfaceBuilder.setSupportingInterfaceList(listSupportingOtucnInterface);
570         org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.Interface1Builder oduIf1Builder =
571             new org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.Interface1Builder();
572
573         oduInterfaceBuilder.addAugmentation(oduIf1Builder.setOdu(oduBuilder.build()).build());
574
575         // Post interface on the device
576         openRoadmInterfaces.postInterface(nodeId, oduInterfaceBuilder);
577         // Post the equipment-state change on the device circuit-pack if xpdr node
578         if (portMap.getLogicalConnectionPoint().contains(StringConstants.NETWORK_TOKEN)) {
579             this.openRoadmInterfaces.postEquipmentState(nodeId, portMap.getSupportingCircuitPackName(), true);
580         }
581         // Update the port-mapping with the interface information
582         this.portMapping.updateMapping(nodeId, portMap);
583         return oduInterfaceBuilder.getName();
584     }
585
586
587     // With SAPI and DAPI information
588     public String createOpenRoadmOtnOducnInterface(String anodeId, String alogicalConnPoint,
589         String supportingOtucn, String znodeId, String zlogicalConnPoint)
590         throws OpenRoadmInterfaceException {
591         Mapping portMapA = portMapping.getMapping(anodeId, alogicalConnPoint);
592         Mapping portMapZ = portMapping.getMapping(znodeId, zlogicalConnPoint);
593         if (portMapA == null) {
594             throw new OpenRoadmInterfaceException(
595                 String.format(MAPPING_ERROR_EXCEPTION_MESSAGE,
596                     anodeId, alogicalConnPoint));
597         }
598         // On the Zside
599         if (portMapZ == null) {
600             throw new OpenRoadmInterfaceException(
601                 String.format(MAPPING_ERROR_EXCEPTION_MESSAGE,
602                     znodeId, zlogicalConnPoint));
603
604         }
605         // Create ODUcn object
606         // Start with OPU object
607         // OPU payload
608         OpuBuilder opuBuilder = new OpuBuilder()
609             .setExpPayloadType(PayloadTypeDef.getDefaultInstance("22"))
610             .setPayloadType(PayloadTypeDef.getDefaultInstance("22"));
611
612         // Create an ODUCn object
613         OduBuilder oduBuilder = new OduBuilder()
614             .setRate(ODUCn.class)
615             .setOduFunction(ODUTTP.class)
616             .setMonitoringMode(MonitoringMode.Terminated)
617             .setTimActEnabled(false)
618             .setTimDetectMode(TimDetectMode.Disabled)
619             .setDegmIntervals(Uint8.valueOf(2))
620             .setDegthrPercentage(Uint16.valueOf(100))
621             .setOpu(opuBuilder.build())
622             .setTxSapi(portMapA.getLcpHashVal())
623             .setTxDapi(portMapZ.getLcpHashVal())
624             .setExpectedSapi(portMapZ.getLcpHashVal())
625             .setExpectedDapi(portMapZ.getLcpHashVal());
626
627         // Set the ODUCn rate from OTUCn interface naming convention
628         String oducnrate = supportingOtucn.substring(supportingOtucn.length() - 1);
629
630         // check if the oducnrate is a valid value and if it is invalid, then throw error
631         if (!SUPPORTED_ODUCN_RATES.contains(oducnrate)) {
632             throw new OpenRoadmInterfaceException(
633                 String.format(RATE_EXCEPTION_MESSAGE));
634         }
635
636         oduBuilder.setOducnNRate(Uint16.valueOf(oducnrate));
637
638         InterfaceBuilder oduInterfaceBuilder = createGenericInterfaceBuilder(portMapA, OtnOdu.class,
639             alogicalConnPoint + ODUC + oducnrate);
640
641         // Create a list
642         List<String> listSupportingOtucnInterface = new ArrayList<>();
643         listSupportingOtucnInterface.add(supportingOtucn);
644
645         oduInterfaceBuilder.setSupportingInterfaceList(listSupportingOtucnInterface);
646         org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.Interface1Builder oduIf1Builder =
647             new org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.Interface1Builder();
648
649         oduInterfaceBuilder.addAugmentation(oduIf1Builder.setOdu(oduBuilder.build()).build());
650
651         // Post interface on the device
652         openRoadmInterfaces.postInterface(anodeId, oduInterfaceBuilder);
653         // Post the equipment-state change on the device circuit-pack if xpdr node
654         if (portMapA.getLogicalConnectionPoint().contains(StringConstants.NETWORK_TOKEN)) {
655             this.openRoadmInterfaces.postEquipmentState(anodeId, portMapA.getSupportingCircuitPackName(), true);
656         }
657         // Update the port-mapping with the interface information
658         this.portMapping.updateMapping(anodeId, portMapA);
659         return oduInterfaceBuilder.getName();
660     }
661
662     // This is only for transponder
663     public String createOpenRoadmOduflexInterface(String nodeId, String logicalConnPoint,
664             String supportingOducn)
665             throws OpenRoadmInterfaceException {
666         Mapping portMap = portMapping.getMapping(nodeId, logicalConnPoint);
667         if (portMap == null) {
668             throw new OpenRoadmInterfaceException(
669                 String.format(MAPPING_ERROR_EXCEPTION_MESSAGE,
670                     nodeId, logicalConnPoint));
671         }
672         // OPU payload
673         OpuBuilder opuBuilder = new OpuBuilder()
674             .setExpPayloadType(PayloadTypeDef.getDefaultInstance("32"))
675             .setPayloadType(PayloadTypeDef.getDefaultInstance("32"));
676
677         // Parent Odu-allocation
678         // Set the trib-slot array
679         List<OpucnTribSlotDef> tribslots = new ArrayList<>();
680         IntStream.range(1, 5).forEach(a -> IntStream.range(1, 21).forEach(b -> tribslots.add(
681             OpucnTribSlotDef.getDefaultInstance(a + "." + b))));
682
683         ParentOduAllocationBuilder parentOduAllocationBuilder = new ParentOduAllocationBuilder()
684             .setTribPortNumber(Uint16.valueOf(1))
685             .setTribSlotsChoice(new OpucnBuilder().setOpucnTribSlots(tribslots).build());
686
687         // Create an ODUFlex object
688         OduBuilder oduBuilder = new OduBuilder()
689             .setRate(ODUflexCbr.class)
690             .setOduflexCbrService(ODUflexCbr400G.class)
691             .setOduFunction(ODUTTPCTP.class)
692             .setMonitoringMode(MonitoringMode.Terminated)
693             .setTimActEnabled(false)
694             .setTimDetectMode(TimDetectMode.Disabled)
695             .setDegmIntervals(Uint8.valueOf(2))
696             .setDegthrPercentage(Uint16.valueOf(100))
697             .setOpu(opuBuilder.build())
698             .setParentOduAllocation(parentOduAllocationBuilder.build());
699
700         InterfaceBuilder oduflexInterfaceBuilder = createGenericInterfaceBuilder(portMap, OtnOdu.class,
701             logicalConnPoint + "-ODUFLEX");
702
703         List<String> listSupportingOtucnInterface = new ArrayList<>();
704         listSupportingOtucnInterface.add(supportingOducn);
705
706         oduflexInterfaceBuilder.setSupportingInterfaceList(listSupportingOtucnInterface);
707
708
709         org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.Interface1Builder
710                 oduflexIf1Builder =
711             new org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.Interface1Builder();
712
713         oduflexInterfaceBuilder.addAugmentation(oduflexIf1Builder.setOdu(oduBuilder.build()).build());
714
715         // Post interface on the device
716         openRoadmInterfaces.postInterface(nodeId, oduflexInterfaceBuilder);
717
718         // Post the equipment-state change on the device circuit-pack if xpdr node
719         if (portMap.getLogicalConnectionPoint().contains(StringConstants.NETWORK_TOKEN)) {
720             this.openRoadmInterfaces.postEquipmentState(nodeId, portMap.getSupportingCircuitPackName(), true);
721         }
722
723         return oduflexInterfaceBuilder.getName();
724     }
725
726     // This is only for transponder; with SAPI/DAPI information
727     public String createOpenRoadmOduflexInterface(String anodeId, String alogicalConnPoint,
728             String supportingOducn, String znodeId, String zlogicalConnPoint)
729             throws OpenRoadmInterfaceException {
730         Mapping portMapA = portMapping.getMapping(anodeId, alogicalConnPoint);
731         Mapping portMapZ = portMapping.getMapping(znodeId, zlogicalConnPoint);
732         if (portMapA == null) {
733             throw new OpenRoadmInterfaceException(
734                 String.format(MAPPING_ERROR_EXCEPTION_MESSAGE,
735                     anodeId, alogicalConnPoint));
736         }
737         // On the Zside
738         if (portMapZ == null) {
739             throw new OpenRoadmInterfaceException(
740                 String.format(MAPPING_ERROR_EXCEPTION_MESSAGE,
741                     znodeId, zlogicalConnPoint));
742
743         }
744         // OPU payload
745         OpuBuilder opuBuilder = new OpuBuilder()
746             .setExpPayloadType(PayloadTypeDef.getDefaultInstance("32"))
747             .setPayloadType(PayloadTypeDef.getDefaultInstance("32"));
748
749         // Parent Odu-allocation
750         // Set the trib-slot array
751         List<OpucnTribSlotDef> tribslots = new ArrayList<>();
752         IntStream.range(1, 5).forEach(a -> IntStream.range(1, 21).forEach(b -> tribslots.add(
753             OpucnTribSlotDef.getDefaultInstance(a + "." + b))));
754
755         ParentOduAllocationBuilder parentOduAllocationBuilder = new ParentOduAllocationBuilder()
756             .setTribPortNumber(Uint16.valueOf(1))
757             .setTribSlotsChoice(new OpucnBuilder().setOpucnTribSlots(tribslots).build());
758
759         // Create an ODUFlex object
760         OduBuilder oduBuilder = new OduBuilder()
761             .setRate(ODUflexCbr.class)
762             .setOduflexCbrService(ODUflexCbr400G.class)
763             .setOduFunction(ODUTTPCTP.class)
764             .setMonitoringMode(MonitoringMode.Terminated)
765             .setTimActEnabled(false)
766             .setTimDetectMode(TimDetectMode.Disabled)
767             .setDegmIntervals(Uint8.valueOf(2))
768             .setDegthrPercentage(Uint16.valueOf(100))
769             .setTxSapi(portMapA.getLcpHashVal())
770             .setTxDapi(portMapZ.getLcpHashVal())
771             .setExpectedSapi(portMapZ.getLcpHashVal())
772             .setExpectedDapi(portMapA.getLcpHashVal())
773             .setOpu(opuBuilder.build())
774             .setParentOduAllocation(parentOduAllocationBuilder.build());
775
776         InterfaceBuilder oduflexInterfaceBuilder = createGenericInterfaceBuilder(portMapA, OtnOdu.class,
777             alogicalConnPoint + "-ODUFLEX");
778
779         List<String> listSupportingOtucnInterface = new ArrayList<>();
780         listSupportingOtucnInterface.add(supportingOducn);
781
782         oduflexInterfaceBuilder.setSupportingInterfaceList(listSupportingOtucnInterface);
783
784
785         org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.Interface1Builder
786                 oduflexIf1Builder =
787             new org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.Interface1Builder();
788
789         oduflexInterfaceBuilder.addAugmentation(oduflexIf1Builder.setOdu(oduBuilder.build()).build());
790
791         // Post interface on the device
792         openRoadmInterfaces.postInterface(anodeId, oduflexInterfaceBuilder);
793
794         // Post the equipment-state change on the device circuit-pack if xpdr node
795         if (portMapA.getLogicalConnectionPoint().contains(StringConstants.NETWORK_TOKEN)) {
796             this.openRoadmInterfaces.postEquipmentState(anodeId, portMapA.getSupportingCircuitPackName(), true);
797         }
798
799         return oduflexInterfaceBuilder.getName();
800     }
801
802     // This creates the name of the interface with slot numbers at the end
803     public String createOpenRoadmOtsiInterfaceName(String logicalConnectionPoint, String spectralSlotName) {
804         return String.join(GridConstant.NAME_PARAMETERS_SEPARATOR, logicalConnectionPoint, spectralSlotName);
805     }
806
807     private InterfaceBuilder createGenericInterfaceBuilder(Mapping portMap, Class<? extends InterfaceType> type,
808             String key) {
809         return new org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.interfaces.grp.InterfaceBuilder()
810             .setDescription("  TBD   ")
811             .setCircuitId("   TBD    ")
812             .setSupportingCircuitPackName(portMap.getSupportingCircuitPackName())
813             .setSupportingPort(portMap.getSupportingPort())
814             .setAdministrativeState(AdminStates.InService)
815             .setType(type)
816             .setName(key)
817             .withKey(new InterfaceKey(key));
818     }
819
820     @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(
821         value = "UPM_UNCALLED_PRIVATE_METHOD",
822         justification = "call in call() method")
823     private int getServiceRate(ModulationFormat modulationFormat, SpectrumInformation spectrumInformation) {
824
825         switch (modulationFormat) {
826             case DpQpsk:
827                 LOG.info("Given modulation format is {} and thus rate is 200G", modulationFormat);
828                 return 200;
829             case DpQam8:
830                 LOG.info("Given modulation format is {} and thus rate is 300G", modulationFormat);
831                 return 300;
832             case DpQam16:
833                 // DpQam16 is possible for both 31.6 or 63.1 GBaud, for which spectral width is different
834                 // Here take the difference of highest and lowest spectral numbers and determine the width
835                 LOG.info("The width with guard band {}", (spectrumInformation.getHigherSpectralSlotNumber()
836                     - spectrumInformation.getLowerSpectralSlotNumber() + 1) * GridConstant.GRANULARITY);
837                 if ((spectrumInformation.getHigherSpectralSlotNumber()
838                     - spectrumInformation.getLowerSpectralSlotNumber() + 1) * GridConstant.GRANULARITY == 50.0) {
839                     // Based on roll-of-factor of 0.5, 50 - 12.5 = 37.5GHz translates to 31.6 GBaud
840                     LOG.info("The baud-rate is 31.6 GBaud");
841                     LOG.info("Given modulation format {} with 31.6 Gbaud rate is 200G", modulationFormat);
842                     return 200;
843                 } else {
844                     // Based on roll-of-factor of 0.5, 87.5 - 12.5 = 75GHz translates to 63.1 GBaud
845                     LOG.info("The baud-rate is 63.1 GBaud");
846                     return 400;
847                 }
848             default:
849                 LOG.error("Modulation format is required to select the rate");
850                 break;
851         }
852         return 0;
853     }
854
855 }