Merge "Refactor ConvertORTopoToTapiTopoTest"
[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.util.ArrayList;
12 import java.util.Arrays;
13 import java.util.HashSet;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Set;
17 import java.util.stream.IntStream;
18 import org.opendaylight.transportpce.common.StringConstants;
19 import org.opendaylight.transportpce.common.fixedflex.GridConstant;
20 import org.opendaylight.transportpce.common.fixedflex.SpectrumInformation;
21 import org.opendaylight.transportpce.common.mapping.PortMapping;
22 import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaceException;
23 import org.opendaylight.transportpce.common.openroadminterfaces.OpenRoadmInterfaces;
24 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.az.api.info.AEndApiInfo;
25 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.device.renderer.rev211004.az.api.info.ZEndApiInfo;
26 import org.opendaylight.yang.gen.v1.http.org.opendaylight.transportpce.portmapping.rev231221.mapping.Mapping;
27 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.attributes.rev200327.TrailTraceOther.TimDetectMode;
28 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.attributes.rev200327.parent.odu.allocation.ParentOduAllocationBuilder;
29 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.attributes.rev200327.parent.odu.allocation.parent.odu.allocation.trib.slots.choice.OpucnBuilder;
30 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.link.types.rev191129.PowerDBm;
31 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.Foic14;
32 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.Foic24;
33 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.Foic28;
34 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.Foic36;
35 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.Foic48;
36 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.FrequencyTHz;
37 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.ModulationFormat;
38 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.ProvisionModeType;
39 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.R100G;
40 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.R100GOtsi;
41 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.R200GOtsi;
42 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.R300GOtsi;
43 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.optical.channel.types.rev200529.R400GOtsi;
44 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev200529.Ofec;
45 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev200529.Off;
46 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev200529.Rsfec;
47 import org.opendaylight.yang.gen.v1.http.org.openroadm.common.types.rev200529.Scfec;
48 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.interfaces.grp.InterfaceBuilder;
49 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.interfaces.grp.InterfaceKey;
50 import org.opendaylight.yang.gen.v1.http.org.openroadm.device.types.rev191129.XpdrNodeTypes;
51 import org.opendaylight.yang.gen.v1.http.org.openroadm.equipment.states.types.rev191129.AdminStates;
52 import org.opendaylight.yang.gen.v1.http.org.openroadm.ethernet.interfaces.rev200529.Interface1Builder;
53 import org.opendaylight.yang.gen.v1.http.org.openroadm.ethernet.interfaces.rev200529.ethernet.container.EthernetBuilder;
54 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev191129.EthernetCsmacd;
55 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev191129.InterfaceType;
56 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev191129.OpticalChannel;
57 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev191129.OtnOdu;
58 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev191129.OtnOtu;
59 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev191129.Otsi;
60 import org.opendaylight.yang.gen.v1.http.org.openroadm.interfaces.rev191129.OtsiGroup;
61 import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev200529.och.container.OchBuilder;
62 import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.tributary.signal.interfaces.rev200529.otsi.attributes.FlexoBuilder;
63 import org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.tributary.signal.interfaces.rev200529.otsi.container.OtsiBuilder;
64 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.ODU4;
65 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.ODUCTP;
66 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.ODUCn;
67 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.ODUTTP;
68 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.ODUTTPCTP;
69 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.ODUflexCbr;
70 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.ODUflexCbr400G;
71 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.OTU4;
72 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.OTUCn;
73 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.OpucnTribSlotDef;
74 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.common.types.rev200327.PayloadTypeDef;
75 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.OduAttributes.MonitoringMode;
76 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.odu.container.OduBuilder;
77 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.opu.OpuBuilder;
78 import org.opendaylight.yang.gen.v1.http.org.openroadm.otn.otu.interfaces.rev200529.otu.container.OtuBuilder;
79 import org.opendaylight.yang.gen.v1.http.org.openroadm.otsi.group.interfaces.rev200529.otsi.group.container.OtsiGroupBuilder;
80 import org.opendaylight.yang.gen.v1.http.org.openroadm.port.types.rev230526.If100GE;
81 import org.opendaylight.yang.gen.v1.http.org.openroadm.port.types.rev230526.IfOCHOTU4ODU4;
82 import org.opendaylight.yang.gen.v1.http.org.openroadm.port.types.rev230526.IfOtsiOtsigroup;
83 import org.opendaylight.yangtools.yang.common.Decimal64;
84 import org.opendaylight.yangtools.yang.common.Uint16;
85 import org.opendaylight.yangtools.yang.common.Uint32;
86 import org.opendaylight.yangtools.yang.common.Uint8;
87 import org.slf4j.Logger;
88 import org.slf4j.LoggerFactory;
89
90 public class OpenRoadmInterface710 {
91     private static final String MODULATION_FMT_EXCEPTION_MESSAGE =
92         "Unable to get the modulation format";
93     private static final String RATE_EXCEPTION_MESSAGE =
94         "Unable to get the rate";
95     private static final String ODUC = "-ODUC";
96     private static final List<String> SUPPORTED_ODUCN_RATES = List.of("1", "2", "3", "4");
97     private final PortMapping portMapping;
98     private final OpenRoadmInterfaces openRoadmInterfaces;
99     private static final Logger LOG = LoggerFactory.getLogger(OpenRoadmInterface710.class);
100
101     public OpenRoadmInterface710(PortMapping portMapping, OpenRoadmInterfaces openRoadmInterfaces) {
102         this.portMapping = portMapping;
103         this.openRoadmInterfaces = openRoadmInterfaces;
104     }
105
106     public String createOpenRoadmEthInterface(String nodeId, String logicalConnPoint)
107             throws OpenRoadmInterfaceException {
108         Mapping portMap = portMapping.getMapping(nodeId, logicalConnPoint);
109         if (portMap == null) {
110             throw new OpenRoadmInterfaceException(
111                 OpenRoadmInterfaceException.mapping_msg_err(nodeId, logicalConnPoint));
112         }
113         InterfaceBuilder ethInterfaceBldr =
114             createGenericInterfaceBuilder(portMap, EthernetCsmacd.VALUE, logicalConnPoint + "-ETHERNET")
115                 .addAugmentation(
116                     // Create Interface1 type object required for adding as augmentation
117                     new Interface1Builder()
118                         .setEthernet(
119                             // Ethernet interface specific data
120                             // We have to differentiate if-100GE vs if-400GE
121                             // Default set to 400G
122                             portMap.getSupportedInterfaceCapability().contains(If100GE.VALUE)
123                                 // There could be different client pluggables on either side QSFP28-LR4 or QSFP28-FR4
124                                 // LR4-requires FEC to off, while FR4 can accept even when FEC is off
125                                 ? new EthernetBuilder().setFec(Off.VALUE).setSpeed(Uint32.valueOf(100000)).build()
126                                 : new EthernetBuilder().setFec(Rsfec.VALUE).setSpeed(Uint32.valueOf(400000)).build())
127                         .build());
128         // Post interface on the device
129         openRoadmInterfaces.postInterface(nodeId, ethInterfaceBldr);
130         // Post the equipment-state change on the device circuit-pack
131         openRoadmInterfaces.postEquipmentState(nodeId, portMap.getSupportingCircuitPackName(), true);
132         return ethInterfaceBldr.getName();
133     }
134
135     public String createOpenRoadmOchInterface(String nodeId, String logicalConnPoint,
136             SpectrumInformation spectrumInformation)
137             throws OpenRoadmInterfaceException {
138         ModulationFormat modulationFormat = ModulationFormat.forName(spectrumInformation.getModulationFormat());
139         if (modulationFormat == null) {
140             modulationFormat =  ModulationFormat.DpQpsk;
141         }
142         Mapping portMap = portMapping.getMapping(nodeId, logicalConnPoint);
143         if (portMap == null) {
144             throw new OpenRoadmInterfaceException(
145                 OpenRoadmInterfaceException.mapping_msg_err(nodeId, logicalConnPoint));
146         }
147         // Create generic interface
148         InterfaceBuilder ochInterfaceBldr =
149             createGenericInterfaceBuilder(
150                     portMap, OpticalChannel.VALUE,
151                     spectrumInformation.getIdentifierFromParams(logicalConnPoint))
152                 .addAugmentation(
153                 // Create Interface1 type object required for adding as augmentation
154                     new org.opendaylight.yang.gen.v1.http.org.openroadm.optical.channel.interfaces.rev200529
155                             .Interface1Builder()
156                         .setOch(
157                             // OCH interface specific data
158                             new OchBuilder()
159                                 .setFrequency(
160                                     new FrequencyTHz(Decimal64.valueOf(spectrumInformation.getCenterFrequency())))
161                                 .setRate(R100G.VALUE)
162                                 .setTransmitPower(new PowerDBm(Decimal64.valueOf("-5")))
163                                 .setModulationFormat(modulationFormat)
164                                 .build())
165                         .build());
166         // Post interface on the device
167         openRoadmInterfaces.postInterface(nodeId, ochInterfaceBldr);
168         // Post the equipment-state change on the device circuit-pack if xpdr node
169         if (portMap.getLogicalConnectionPoint().contains(StringConstants.NETWORK_TOKEN)) {
170             this.openRoadmInterfaces.postEquipmentState(nodeId, portMap.getSupportingCircuitPackName(), true);
171         }
172         return ochInterfaceBldr.getName();
173     }
174
175     public String createOpenRoadmOtsiInterface(String nodeId, String logicalConnPoint,
176             SpectrumInformation spectrumInformation)
177             throws OpenRoadmInterfaceException {
178         ModulationFormat modulationFormat = ModulationFormat.forName(spectrumInformation.getModulationFormat());
179         if (modulationFormat == null) {
180             throw new OpenRoadmInterfaceException(MODULATION_FMT_EXCEPTION_MESSAGE);
181         }
182         // OTSI interface specific data
183         OtsiBuilder otsiBuilder = new OtsiBuilder()
184             .setFrequency(new FrequencyTHz(Decimal64.valueOf(spectrumInformation.getCenterFrequency())))
185             .setTransmitPower(new PowerDBm(Decimal64.valueOf("-5")))
186             .setProvisionMode(ProvisionModeType.Explicit)
187             .setFec(Ofec.VALUE)
188             .setModulationFormat(modulationFormat);
189         // Use the rate to switch rather than modulation format
190         int serviceRate = getServiceRate(modulationFormat, spectrumInformation);
191         switch (serviceRate) {
192             case 100:
193                 LOG.info("Given modulation format and spectral width 50GHz {} and thus rate is 100G",
194                     modulationFormat);
195                 // TODO check if FOIC and Gbaud logs could not be rationalized
196                 LOG.info("FOIC is 1.4 for 31.6 Gbaud and rate is 100");
197                 otsiBuilder
198                     .setOtsiRate(R100GOtsi.VALUE)
199                     .setFlexo(new FlexoBuilder()
200                         .setFoicType(Foic14.VALUE)
201                         .setIid(new ArrayList<>(Arrays.asList(Uint8.valueOf(1))))
202                         .build());
203                 break;
204             case 200:
205                 LOG.info("Given modulation format is {} and thus rate is 200G", modulationFormat);
206                 FlexoBuilder flexoBuilder = new FlexoBuilder()
207                     .setIid(new ArrayList<>(List.of(Uint8.valueOf(1), Uint8.valueOf(2))));
208                 if (modulationFormat == ModulationFormat.DpQam16) {
209                     LOG.info("FOIC is 2.8 for 31.6 Gbaud and rate is 200");
210                     // FOIC rate is different
211                     flexoBuilder.setFoicType(Foic28.VALUE);
212                 } else {
213                     // default is dp-qpsk for 200G under 63.1 GBaud
214                     flexoBuilder.setFoicType(Foic24.VALUE);
215                 }
216                 otsiBuilder
217                     .setOtsiRate(R200GOtsi.VALUE)
218                     .setFlexo(flexoBuilder.build());
219                 break;
220             case 300:
221                 LOG.info("Given modulation format is {} and thus rate is 300G", modulationFormat);
222                 otsiBuilder.setOtsiRate(R300GOtsi.VALUE)
223                     .setFlexo(new FlexoBuilder()
224                         .setFoicType(Foic36.VALUE)
225                         .setIid(new ArrayList<>(List.of(Uint8.valueOf(1), Uint8.valueOf(2), Uint8.valueOf(3))))
226                         .build());
227                 break;
228             case 400:
229                 // Default baud-rate is 63.1 Gbaud
230                 LOG.info("Given modulation format is {} and thus rate is 400G", modulationFormat);
231                 otsiBuilder
232                     .setModulationFormat(modulationFormat)
233                     .setOtsiRate(R400GOtsi.VALUE)
234                     .setFlexo(new FlexoBuilder()
235                         .setFoicType(Foic48.VALUE)
236                         .setIid(new ArrayList<>(
237                             List.of(Uint8.valueOf(1), Uint8.valueOf(2), Uint8.valueOf(3), Uint8.valueOf(4))))
238                         .build());
239                 break;
240             default:
241                 LOG.error("Rate {} is unsupported", serviceRate);
242                 throw new OpenRoadmInterfaceException(RATE_EXCEPTION_MESSAGE);
243         }
244         Mapping portMap = portMapping.getMapping(nodeId, logicalConnPoint);
245         if (portMap == null) {
246             throw new OpenRoadmInterfaceException(
247                 OpenRoadmInterfaceException.mapping_msg_err(nodeId, logicalConnPoint));
248         }
249         // Create generic interface
250         InterfaceBuilder otsiInterfaceBldr =
251             createGenericInterfaceBuilder(
252                     portMap, Otsi.VALUE,
253                     spectrumInformation.getIdentifierFromParams(logicalConnPoint))
254                 .addAugmentation(
255                     // Create Interface1 type object required for adding as augmentation
256                     new org.opendaylight.yang.gen.v1.http
257                             .org.openroadm.optical.channel.tributary.signal.interfaces.rev200529.Interface1Builder()
258                         .setOtsi(otsiBuilder.build())
259                         .build());
260         // Post interface on the device
261         openRoadmInterfaces.postInterface(nodeId, otsiInterfaceBldr);
262         // Post the equipment-state change on the device circuit-pack if xpdr node
263         if (portMap.getLogicalConnectionPoint().contains(StringConstants.NETWORK_TOKEN)) {
264             this.openRoadmInterfaces.postEquipmentState(nodeId, portMap.getSupportingCircuitPackName(), true);
265         }
266         return otsiInterfaceBldr.getName();
267     }
268
269     // This is a transponder use-case where the supporting port is just one, but YANG model
270     // requires supporting port to be list
271     public String createOpenRoadmOtsiGroupInterface(String nodeId, String logicalConnPoint,
272             String supportingOtsiInterface, SpectrumInformation spectrumInformation)
273             throws OpenRoadmInterfaceException {
274         Mapping portMap = portMapping.getMapping(nodeId, logicalConnPoint);
275         if (portMap == null) {
276             throw new OpenRoadmInterfaceException(
277                 OpenRoadmInterfaceException.mapping_msg_err(nodeId, logicalConnPoint));
278         }
279         // Check the modulation format
280         ModulationFormat modulationFormat = ModulationFormat.forName(spectrumInformation.getModulationFormat());
281         if (modulationFormat == null) {
282             throw new OpenRoadmInterfaceException(MODULATION_FMT_EXCEPTION_MESSAGE);
283         }
284         int serviceRate = getServiceRate(modulationFormat, spectrumInformation);
285         // Create an OTSI group object
286         OtsiGroupBuilder otsiGroupBuilder = new OtsiGroupBuilder().setGroupId(Uint32.valueOf(1));
287         switch (serviceRate) {
288             case 100:
289                 otsiGroupBuilder.setGroupRate(R100GOtsi.VALUE);
290                 break;
291             case 200:
292                 otsiGroupBuilder.setGroupRate(R200GOtsi.VALUE);
293                 break;
294             case 300:
295                 otsiGroupBuilder.setGroupRate(R300GOtsi.VALUE);
296                 break;
297             case 400:
298                 otsiGroupBuilder.setGroupRate(R400GOtsi.VALUE);
299                 break;
300             default:
301                 LOG.error("Rate {} is not supported", serviceRate);
302                 throw new OpenRoadmInterfaceException(RATE_EXCEPTION_MESSAGE);
303         }
304         // Create generic interface
305         InterfaceBuilder otsiGroupInterfaceBldr =
306             createGenericInterfaceBuilder(
307                     portMap, OtsiGroup.VALUE,
308                     logicalConnPoint + String.join("-", "", "OTSIGROUP", serviceRate + "G"))
309                 .setSupportingInterfaceList(new HashSet<>(Set.of(supportingOtsiInterface)))
310                 .addAugmentation(
311                     new org.opendaylight.yang.gen.v1.http.org.openroadm.otsi.group.interfaces.rev200529
312                             .Interface1Builder()
313                         .setOtsiGroup(otsiGroupBuilder.build())
314                         .build());
315         // Post interface on the device
316         openRoadmInterfaces.postInterface(nodeId, otsiGroupInterfaceBldr);
317         // Post the equipment-state change on the device circuit-pack if xpdr node
318         if (portMap.getLogicalConnectionPoint().contains(StringConstants.NETWORK_TOKEN)) {
319             this.openRoadmInterfaces.postEquipmentState(nodeId, portMap.getSupportingCircuitPackName(), true);
320         }
321         return otsiGroupInterfaceBldr.getName();
322     }
323
324     public String createOpenRoadmOchOtsiOtsigroupInterface(String nodeId, String logicalConnPoint,
325             SpectrumInformation spectrumInformation)
326             throws OpenRoadmInterfaceException {
327         Mapping portMap = portMapping.getMapping(nodeId, logicalConnPoint);
328         if (portMap == null) {
329             throw new OpenRoadmInterfaceException(
330                 OpenRoadmInterfaceException.mapping_msg_err(nodeId, logicalConnPoint));
331         }
332         if (portMap.getSupportedInterfaceCapability().contains(IfOCHOTU4ODU4.VALUE)) {
333             // create OCH interface
334             return createOpenRoadmOchInterface(nodeId, logicalConnPoint, spectrumInformation);
335         }
336         if (portMap.getSupportedInterfaceCapability().contains(IfOtsiOtsigroup.VALUE)) {
337             // Create OTSi and OTSi-group and concat the names of the interface
338             String interfaceOtsiName = createOpenRoadmOtsiInterface(nodeId, logicalConnPoint, spectrumInformation);
339             // And Concat the two names for this interface
340             return interfaceOtsiName + "#"
341                 + createOpenRoadmOtsiGroupInterface(nodeId, logicalConnPoint, interfaceOtsiName, spectrumInformation);
342         }
343         return null;
344     }
345
346     public String createOpenRoadmOtu4Interface(String nodeId, String logicalConnPoint, String supportOchInterface,
347             AEndApiInfo apiInfoA, ZEndApiInfo apiInfoZ) throws OpenRoadmInterfaceException {
348         Mapping mapping = this.portMapping.getMapping(nodeId, logicalConnPoint);
349         if (mapping == null) {
350             throw new OpenRoadmInterfaceException(
351                 OpenRoadmInterfaceException.mapping_msg_err(nodeId, logicalConnPoint));
352         }
353         // OTU interface specific data
354         org.opendaylight.yang.gen.v1.http.org.openroadm.otn.otu.interfaces.rev200529.otu.container.OtuBuilder
355                 otuIfBuilder =
356             new org.opendaylight.yang.gen.v1.http.org.openroadm.otn.otu.interfaces.rev200529.otu.container.OtuBuilder()
357                 .setFec(Scfec.VALUE)
358                 .setRate(OTU4.VALUE);
359         if (apiInfoA != null) {
360             otuIfBuilder.setTxSapi(apiInfoA.getSapi())
361                 .setTxDapi(apiInfoA.getDapi())
362                 .setExpectedSapi(apiInfoA.getExpectedSapi())
363                 .setExpectedDapi(apiInfoA.getExpectedDapi());
364         }
365         if (apiInfoZ != null) {
366             otuIfBuilder.setTxSapi(apiInfoZ.getSapi())
367                 .setTxDapi(apiInfoZ.getDapi())
368                 .setExpectedSapi(apiInfoZ.getExpectedSapi())
369                 .setExpectedDapi(apiInfoZ.getExpectedDapi());
370         }
371         InterfaceBuilder otuInterfaceBldr =
372             createGenericInterfaceBuilder(mapping, OtnOtu.VALUE, logicalConnPoint + "-OTU4")
373                 .setSupportingInterfaceList(new HashSet<>(Set.of(supportOchInterface)))
374                 .addAugmentation(
375                     // Create Interface1 type object required for adding as augmentation
376                     new org.opendaylight.yang.gen.v1.http.org.openroadm.otn.otu.interfaces.rev200529.Interface1Builder()
377                         .setOtu(otuIfBuilder.build())
378                         .build());
379         // Post interface on the device
380         openRoadmInterfaces.postInterface(nodeId, otuInterfaceBldr);
381         this.portMapping.updateMapping(nodeId, mapping);
382         return otuInterfaceBldr.getName();
383     }
384
385
386     public String createOpenRoadmOtucnInterface(String nodeId, String logicalConnPoint,
387             String supportingOtsiGroupInterface, AEndApiInfo apiInfoA, ZEndApiInfo apiInfoZ)
388             throws OpenRoadmInterfaceException {
389         Mapping mapping = portMapping.getMapping(nodeId, logicalConnPoint);
390         if (mapping == null) {
391             throw new OpenRoadmInterfaceException(
392                 OpenRoadmInterfaceException.mapping_msg_err(nodeId, logicalConnPoint));
393         }
394         // Create an OTUCn object
395         OtuBuilder otuBuilder = new OtuBuilder()
396             .setRate(OTUCn.VALUE)
397             .setTimActEnabled(false)
398             .setTimDetectMode(TimDetectMode.Disabled)
399             .setDegmIntervals(Uint8.valueOf(2))
400             .setDegthrPercentage(Uint16.valueOf(100));
401         if (apiInfoA != null) {
402             otuBuilder.setTxSapi(apiInfoA.getSapi())
403                 .setTxDapi(apiInfoA.getDapi())
404                 .setExpectedSapi(apiInfoA.getExpectedSapi())
405                 .setExpectedDapi(apiInfoA.getExpectedDapi());
406         }
407         if (apiInfoZ != null) {
408             otuBuilder.setTxSapi(apiInfoZ.getSapi())
409                 .setTxDapi(apiInfoZ.getDapi())
410                 .setExpectedSapi(apiInfoZ.getExpectedSapi())
411                 .setExpectedDapi(apiInfoZ.getExpectedDapi());
412         }
413         // Set the OTUCn rate for various rates
414         String rate = supportingOtsiGroupInterface.substring(supportingOtsiGroupInterface.lastIndexOf('-') + 1);
415         String otucnrate = null;
416         switch (rate) {
417             case "100G":
418                 otuBuilder.setOtucnNRate(Uint16.valueOf(1));
419                 otucnrate = "1";
420                 break;
421             case "200G":
422                 otuBuilder.setOtucnNRate(Uint16.valueOf(2));
423                 otucnrate = "2";
424                 break;
425             case "300G":
426                 otuBuilder.setOtucnNRate(Uint16.valueOf(3));
427                 otucnrate = "3";
428                 break;
429             case "400G":
430                 otuBuilder.setOtucnNRate(Uint16.valueOf(4));
431                 otucnrate = "4";
432                 break;
433             default:
434                 LOG.error("Rate {} is not supported", rate);
435                 throw new OpenRoadmInterfaceException(RATE_EXCEPTION_MESSAGE);
436         }
437         InterfaceBuilder otuInterfaceBuilder =
438             createGenericInterfaceBuilder(mapping, OtnOtu.VALUE, logicalConnPoint + "-OTUC" + otucnrate)
439                 .setSupportingInterfaceList(new HashSet<>(Set.of(supportingOtsiGroupInterface)))
440                 .addAugmentation(
441                     new org.opendaylight.yang.gen.v1.http.org.openroadm.otn.otu.interfaces.rev200529.Interface1Builder()
442                         .setOtu(otuBuilder.build())
443                         .build());
444         // Post interface on the device
445         openRoadmInterfaces.postInterface(nodeId, otuInterfaceBuilder);
446         // Post the equipment-state change on the device circuit-pack if xpdr node
447         if (mapping.getLogicalConnectionPoint().contains(StringConstants.NETWORK_TOKEN)) {
448             this.openRoadmInterfaces.postEquipmentState(nodeId, mapping.getSupportingCircuitPackName(), true);
449         }
450         this.portMapping.updateMapping(nodeId, mapping);
451         return otuInterfaceBuilder.getName();
452     }
453
454     public String createOpenRoadmOtu4OtucnInterface(String nodeId, String logicalConnPoint,
455             String supportingInterface, AEndApiInfo apiInfoA, ZEndApiInfo apiInfoZ)
456             throws OpenRoadmInterfaceException {
457         Mapping portMap = portMapping.getMapping(nodeId, logicalConnPoint);
458         if (portMap == null) {
459             throw new OpenRoadmInterfaceException(
460                 OpenRoadmInterfaceException.mapping_msg_err(nodeId, logicalConnPoint));
461         }
462         // Depending on OCH-OTU4-ODU4 interface or OTSi-OTSi-group, supporting interface should
463         // reflect that
464         if (portMap.getSupportedInterfaceCapability().contains(IfOCHOTU4ODU4.VALUE)) {
465             // create OTU4 interface
466             return createOpenRoadmOtu4Interface(nodeId, logicalConnPoint, supportingInterface, apiInfoA, apiInfoZ);
467         }
468         if (portMap.getSupportedInterfaceCapability().contains(IfOtsiOtsigroup.VALUE)) {
469             // Create OTUCn
470             return createOpenRoadmOtucnInterface(nodeId, logicalConnPoint, supportingInterface, apiInfoA, apiInfoZ);
471         }
472         return null;
473     }
474
475     public String createOpenRoadmOdu4Interface(String nodeId, String logicalConnPoint,
476             AEndApiInfo apiInfoA, ZEndApiInfo apiInfoZ) throws OpenRoadmInterfaceException {
477         Mapping mapping = portMapping.getMapping(nodeId, logicalConnPoint);
478         if (mapping == null) {
479             throw new OpenRoadmInterfaceException(
480                 OpenRoadmInterfaceException.mapping_msg_err(nodeId, logicalConnPoint));
481         }
482         InterfaceBuilder oduInterfaceBldr =
483             createGenericInterfaceBuilder(mapping, OtnOdu.VALUE, logicalConnPoint + "-ODU4");
484         if (mapping.getSupportingOtu4() != null) {
485             oduInterfaceBldr.setSupportingInterfaceList(new HashSet<>(Set.of(mapping.getSupportingOtu4())));
486         }
487         // Create an ODU4 object
488         OduBuilder oduBuilder = new OduBuilder()
489             .setRate(ODU4.VALUE)
490             .setOduFunction(ODUTTP.VALUE)
491             .setMonitoringMode(MonitoringMode.Terminated)
492             .setOpu(
493                 // OPU payload
494                 new OpuBuilder()
495                     .setExpPayloadType(PayloadTypeDef.getDefaultInstance("07"))
496                     .setPayloadType(PayloadTypeDef.getDefaultInstance("07"))
497                     .build());
498         if (apiInfoA != null) {
499             oduBuilder.setTxSapi(apiInfoA.getSapi())
500                 .setTxDapi(apiInfoA.getDapi())
501                 .setExpectedSapi(apiInfoA.getExpectedSapi())
502                 .setExpectedDapi(apiInfoA.getExpectedDapi());
503         }
504         if (apiInfoZ != null) {
505             oduBuilder.setTxSapi(apiInfoZ.getSapi())
506                 .setTxDapi(apiInfoZ.getDapi())
507                 .setExpectedSapi(apiInfoZ.getExpectedSapi())
508                 .setExpectedDapi(apiInfoZ.getExpectedDapi());
509         }
510         oduInterfaceBldr
511             .addAugmentation(
512                 new org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.Interface1Builder()
513                     .setOdu(oduBuilder.build())
514                 .build());
515         // Post interface on the device
516         openRoadmInterfaces.postInterface(nodeId, oduInterfaceBldr);
517         // Since this is not a CTP, we can update the port-mapping
518         LOG.info("{}-{} updating mapping with interface {}", nodeId, logicalConnPoint, oduInterfaceBldr.getName());
519         this.portMapping.updateMapping(nodeId, mapping);
520         return oduInterfaceBldr.getName();
521     }
522
523
524     public String createOpenRoadmOducnInterface(String nodeId, String logicalConnPoint)
525             throws OpenRoadmInterfaceException {
526         Mapping portMap = portMapping.getMapping(nodeId, logicalConnPoint);
527         if (portMap == null) {
528             throw new OpenRoadmInterfaceException(
529                 OpenRoadmInterfaceException.mapping_msg_err(nodeId, logicalConnPoint));
530         }
531         // Used to find if the port is regen-type
532         if (portMap.getXpdrType() == null) {
533             throw new OpenRoadmInterfaceException(
534                     OpenRoadmInterfaceException.mapping_xpdrtype_err(nodeId, logicalConnPoint));
535         }
536         if (portMap.getSupportingOtucn() == null) {
537             throw new OpenRoadmInterfaceException("Missing supporting OTUCn interface on port-mapping");
538         }
539         String supportingOtucn = portMap.getSupportingOtucn();
540         // Set the ODUCn rate from OTUCn interface naming convention
541         String oducnrate = supportingOtucn.substring(supportingOtucn.length() - 1);
542         // check if the oducnrate is a valid value and if it is invalid, then throw error
543         if (!SUPPORTED_ODUCN_RATES.contains(oducnrate)) {
544             throw new OpenRoadmInterfaceException(RATE_EXCEPTION_MESSAGE);
545         }
546         // set the common parameters
547         OduBuilder oduBuilder = new OduBuilder()
548                                     .setRate(ODUCn.VALUE)
549                                     .setOducnNRate(Uint16.valueOf(oducnrate));
550
551         if (portMap.getXpdrType() == XpdrNodeTypes.Regen) {
552             LOG.info("Regen mode only supports not-terminated or monitored");
553             oduBuilder.setMonitoringMode(MonitoringMode.NotTerminated)
554                     .setOduFunction(ODUCTP.VALUE);
555         } else {
556             // if it is other than regen mode
557             oduBuilder.setMonitoringMode(MonitoringMode.Terminated)
558                     .setTimActEnabled(false)
559                     .setOduFunction(ODUTTP.VALUE)
560                     .setTimDetectMode(TimDetectMode.Disabled)
561                     .setDegmIntervals(Uint8.valueOf(2))
562                     .setDegthrPercentage(Uint16.valueOf(100))
563                     .setOducnNRate(Uint16.valueOf(oducnrate))
564                     .setOpu(
565                             // OPU payload
566                             new OpuBuilder()
567                                     .setExpPayloadType(PayloadTypeDef.getDefaultInstance("22"))
568                                     .setPayloadType(PayloadTypeDef.getDefaultInstance("22"))
569                                     .build());
570         }
571
572         InterfaceBuilder oduInterfaceBuilder =
573             createGenericInterfaceBuilder(portMap, OtnOdu.VALUE, logicalConnPoint + "-ODUC" + oducnrate)
574                 .setSupportingInterfaceList(new HashSet<>(Set.of(supportingOtucn)))
575                 .addAugmentation(
576                     new org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.Interface1Builder()
577                         .setOdu(oduBuilder.build())
578                             .build());
579         // Post interface on the device
580         openRoadmInterfaces.postInterface(nodeId, oduInterfaceBuilder);
581         // Post the equipment-state change on the device circuit-pack if xpdr node
582         if (portMap.getLogicalConnectionPoint().contains(StringConstants.NETWORK_TOKEN)) {
583             this.openRoadmInterfaces.postEquipmentState(nodeId, portMap.getSupportingCircuitPackName(), true);
584         }
585         return oduInterfaceBuilder.getName();
586     }
587
588     // Overloaded methods should be together
589     // With SAPI and DAPI information
590     public String createOpenRoadmOducnInterface(String anodeId, String alogicalConnPoint,
591             String supportingOtucn, String znodeId, String zlogicalConnPoint)
592             throws OpenRoadmInterfaceException {
593         // Set the ODUCn rate from OTUCn interface naming convention
594         String oducnrate = supportingOtucn.substring(supportingOtucn.length() - 1);
595         // check if the oducnrate is a valid value and if it is invalid, then throw error
596         if (!SUPPORTED_ODUCN_RATES.contains(oducnrate)) {
597             throw new OpenRoadmInterfaceException(RATE_EXCEPTION_MESSAGE);
598         }
599         Mapping portMapA = portMapping.getMapping(anodeId, alogicalConnPoint);
600         if (portMapA == null) {
601             throw new OpenRoadmInterfaceException(
602                 OpenRoadmInterfaceException.mapping_msg_err(anodeId, alogicalConnPoint));
603         }
604         if (portMapA.getXpdrType() == null) {
605             throw new OpenRoadmInterfaceException(
606                     OpenRoadmInterfaceException.mapping_xpdrtype_err(anodeId, alogicalConnPoint));
607         }
608         // On the Zside
609         Mapping portMapZ = portMapping.getMapping(znodeId, zlogicalConnPoint);
610         if (portMapZ == null) {
611             throw new OpenRoadmInterfaceException(
612                 OpenRoadmInterfaceException.mapping_msg_err(znodeId, zlogicalConnPoint));
613         }
614         // set the common parameters
615         OduBuilder oduBuilder = new OduBuilder()
616                 .setRate(ODUCn.VALUE)
617                 .setOducnNRate(Uint16.valueOf(oducnrate));
618
619         if (portMapA.getXpdrType() == XpdrNodeTypes.Regen) {
620             LOG.info("Regen mode only supports not-terminated or monitored");
621             oduBuilder.setMonitoringMode(MonitoringMode.NotTerminated)
622                     // For regen-mode ODU-function is set to CTP
623                     .setOduFunction(ODUCTP.VALUE);
624         } else {
625             // if it is other than regen mode
626             oduBuilder.setMonitoringMode(MonitoringMode.Terminated)
627                     .setTimActEnabled(false)
628                     .setOduFunction(ODUTTP.VALUE)
629                     .setTimDetectMode(TimDetectMode.Disabled)
630                     .setDegmIntervals(Uint8.valueOf(2))
631                     .setDegthrPercentage(Uint16.valueOf(100))
632                     .setOducnNRate(Uint16.valueOf(oducnrate))
633                     .setOpu(
634                             // OPU payload
635                             new OpuBuilder()
636                                     .setExpPayloadType(PayloadTypeDef.getDefaultInstance("22"))
637                                     .setPayloadType(PayloadTypeDef.getDefaultInstance("22"))
638                                     .build())
639                     .setTxSapi(portMapA.getLcpHashVal())
640                     .setTxDapi(portMapZ.getLcpHashVal())
641                     .setExpectedSapi(portMapZ.getLcpHashVal())
642                     .setExpectedDapi(portMapZ.getLcpHashVal());
643         }
644
645         InterfaceBuilder oduInterfaceBuilder =
646             createGenericInterfaceBuilder(portMapA, OtnOdu.VALUE, alogicalConnPoint + ODUC + oducnrate)
647                 .setSupportingInterfaceList(new HashSet<>(Set.of(supportingOtucn)))
648                 .addAugmentation(
649                     new org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.Interface1Builder()
650                         .setOdu(oduBuilder.build())
651                         .build());
652         // Post interface on the device
653         openRoadmInterfaces.postInterface(anodeId, oduInterfaceBuilder);
654         // Post the equipment-state change on the device circuit-pack if xpdr node
655         if (portMapA.getLogicalConnectionPoint().contains(StringConstants.NETWORK_TOKEN)) {
656             this.openRoadmInterfaces.postEquipmentState(anodeId, portMapA.getSupportingCircuitPackName(), true);
657         }
658         return oduInterfaceBuilder.getName();
659     }
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                 OpenRoadmInterfaceException.mapping_msg_err(nodeId, logicalConnPoint));
670         }
671         // Parent Odu-allocation
672         // Set the trib-slot array
673         Set<OpucnTribSlotDef> tribslots = new HashSet<>();
674         // Here the int stream is based on rate
675         // Get the rate, which can be 1, 2, 3 or 4 4=400G, 1=100G
676         String rate = supportingOducn.substring(supportingOducn.length() - 1);
677         IntStream.range(1, Integer.parseInt(rate) + 1)
678             .forEach(a -> IntStream.range(1, 21)
679                 .forEach(b -> tribslots.add(OpucnTribSlotDef.getDefaultInstance(a + "." + b))));
680         // Create an ODUFlex object
681         OduBuilder oduBuilder = new OduBuilder()
682             .setOduFunction(ODUTTPCTP.VALUE)
683             .setMonitoringMode(MonitoringMode.Terminated)
684             .setTimActEnabled(false)
685             .setTimDetectMode(TimDetectMode.Disabled)
686             .setDegmIntervals(Uint8.valueOf(2))
687             .setDegthrPercentage(Uint16.valueOf(100))
688             .setParentOduAllocation(
689                 new ParentOduAllocationBuilder()
690                     .setTribPortNumber(Uint16.valueOf(1))
691                     .setTribSlotsChoice(new OpucnBuilder().setOpucnTribSlots(tribslots).build())
692                     .build());
693         // Build the OPU container to the ODU builder
694         switch (rate) {
695             case "1":
696                 oduBuilder
697                     .setRate(ODU4.VALUE)
698                     .setOpu(
699                         new OpuBuilder()
700                             .setExpPayloadType(PayloadTypeDef.getDefaultInstance("07"))
701                             .setPayloadType(PayloadTypeDef.getDefaultInstance("07"))
702                             .build());
703                 logicalConnPoint += "-ODU4";
704                 break;
705             case "4":
706                 oduBuilder
707                     .setRate(ODUflexCbr.VALUE)
708                     .setOduflexCbrService(ODUflexCbr400G.VALUE)
709                     .setOpu(
710                         new OpuBuilder()
711                             .setExpPayloadType(PayloadTypeDef.getDefaultInstance("32"))
712                             .setPayloadType(PayloadTypeDef.getDefaultInstance("32"))
713                             .build());
714                 logicalConnPoint += "-ODUFLEX";
715                 break;
716             default:
717                 oduBuilder.setOpu(new OpuBuilder().build());
718                 break;
719         }
720         InterfaceBuilder oduflexInterfaceBuilder =
721             createGenericInterfaceBuilder(portMap, OtnOdu.VALUE, logicalConnPoint)
722                 .setSupportingInterfaceList(new HashSet<>(Set.of(supportingOducn)))
723                 .addAugmentation(
724                     new org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.Interface1Builder()
725                         .setOdu(oduBuilder.build())
726                         .build());
727         // Post interface on the device
728         openRoadmInterfaces.postInterface(nodeId, oduflexInterfaceBuilder);
729         // Post the equipment-state change on the device circuit-pack if xpdr node
730         if (portMap.getLogicalConnectionPoint().contains(StringConstants.NETWORK_TOKEN)) {
731             this.openRoadmInterfaces.postEquipmentState(nodeId, portMap.getSupportingCircuitPackName(), true);
732         }
733         return oduflexInterfaceBuilder.getName();
734     }
735
736     // Overloaded methods should be together
737     // This is only for transponder; with SAPI/DAPI information
738     public String createOpenRoadmOduflexInterface(String anodeId, String alogicalConnPoint,
739             String supportingOducn, String znodeId, String zlogicalConnPoint)
740             throws OpenRoadmInterfaceException {
741         Mapping portMapA = portMapping.getMapping(anodeId, alogicalConnPoint);
742         if (portMapA == null) {
743             throw new OpenRoadmInterfaceException(
744                 OpenRoadmInterfaceException.mapping_msg_err(anodeId, alogicalConnPoint));
745         }
746         // On the Zside
747         Mapping portMapZ = portMapping.getMapping(znodeId, zlogicalConnPoint);
748         if (portMapZ == null) {
749             throw new OpenRoadmInterfaceException(
750                 OpenRoadmInterfaceException.mapping_msg_err(znodeId, zlogicalConnPoint));
751         }
752         // Parent Odu-allocation
753         // Set the trib-slot array
754         Set<OpucnTribSlotDef> tribslots = new HashSet<>();
755         // Here the int stream is based on rate
756         // Get the rate, which can be 1, 2, 3 or 4 4=400G, 1=100G
757         String rate = supportingOducn.substring(supportingOducn.lastIndexOf('-') + 1);
758         IntStream.range(1, Integer.parseInt(rate) + 1)
759             .forEach(a -> IntStream.range(1, 21)
760                 .forEach(b -> tribslots.add(OpucnTribSlotDef.getDefaultInstance(a + "." + b))));
761         // Create an ODUFlex object
762         OduBuilder oduBuilder = new OduBuilder()
763             .setOduFunction(ODUTTPCTP.VALUE)
764             .setMonitoringMode(MonitoringMode.Terminated)
765             .setTimActEnabled(false)
766             .setTimDetectMode(TimDetectMode.Disabled)
767             .setDegmIntervals(Uint8.valueOf(2))
768             .setDegthrPercentage(Uint16.valueOf(100))
769             // TODO the following line seemed to come a bit early
770             // so it is now commented out and the code was aligned with previous method
771             //.setOpu(opuBuilder.build())
772             .setParentOduAllocation(
773                 new ParentOduAllocationBuilder()
774                     .setTribPortNumber(Uint16.valueOf(1))
775                     .setTribSlotsChoice(new OpucnBuilder().setOpucnTribSlots(tribslots).build())
776                     .build());
777         switch (rate) {
778             case "1":
779                 oduBuilder
780                     .setRate(ODU4.VALUE)
781                     .setOpu(
782                         new OpuBuilder()
783                             .setExpPayloadType(PayloadTypeDef.getDefaultInstance("07"))
784                             .setPayloadType(PayloadTypeDef.getDefaultInstance("07"))
785                             .build());
786                 alogicalConnPoint += "-ODU4";
787                 break;
788             case "4":
789                 oduBuilder
790                     .setRate(ODUflexCbr.VALUE)
791                     .setOduflexCbrService(ODUflexCbr400G.VALUE)
792                     .setOpu(
793                         new OpuBuilder()
794                             .setExpPayloadType(PayloadTypeDef.getDefaultInstance("32"))
795                             .setPayloadType(PayloadTypeDef.getDefaultInstance("32"))
796                             .build());
797                 alogicalConnPoint += "-ODUFLEX";
798                 break;
799             default:
800                 oduBuilder.setOpu(new OpuBuilder().build());
801                 break;
802         }
803         InterfaceBuilder oduflexInterfaceBuilder =
804             createGenericInterfaceBuilder(portMapA, OtnOdu.VALUE, alogicalConnPoint)
805                 .setSupportingInterfaceList(new HashSet<>(Set.of(supportingOducn)))
806                 .addAugmentation(
807                     new org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.Interface1Builder()
808                         .setOdu(oduBuilder.build())
809                         .build());
810         // Post the equipment-state change on the device circuit-pack if xpdr node
811         if (portMapA.getLogicalConnectionPoint().contains(StringConstants.NETWORK_TOKEN)) {
812             this.openRoadmInterfaces.postEquipmentState(anodeId, portMapA.getSupportingCircuitPackName(), true);
813         }
814         return oduflexInterfaceBuilder.getName();
815     }
816
817     public String createOpenRoadmOdu4OducnOduflex(String nodeId, String logicalConnPoint,
818             AEndApiInfo apiInfoA, ZEndApiInfo apiInfoZ) throws OpenRoadmInterfaceException {
819         Mapping portMap = portMapping.getMapping(nodeId, logicalConnPoint);
820         if (portMap == null) {
821             throw new OpenRoadmInterfaceException(
822                 OpenRoadmInterfaceException.mapping_msg_err(nodeId, logicalConnPoint));
823         }
824         // Depending on OTU4 or OTUCn, supporting interface should
825         // reflect that
826         String interfaceOdu4OducnOduflex = null;
827         // Depending on OTU4 or OTUCn, supporting interface should reflect that
828         if (portMap.getSupportedInterfaceCapability().contains(IfOCHOTU4ODU4.VALUE)) {
829             // create OTU4 interface
830             return createOpenRoadmOdu4Interface(nodeId, logicalConnPoint, apiInfoA, apiInfoZ);
831         }
832         if (portMap.getSupportedInterfaceCapability().contains(IfOtsiOtsigroup.VALUE)) {
833             // Create ODUCn and ODUFlex interface.
834             String interfaceOducn = createOpenRoadmOducnInterface(nodeId, logicalConnPoint);
835             return interfaceOducn + "#"
836                 + createOpenRoadmOduflexInterface(nodeId, logicalConnPoint, interfaceOducn);
837         }
838         return null;
839     }
840
841     public String createOpenRoadmOtnOducnInterface(String nodeId, String logicalConnPoint,
842             String supportingOtucn)
843             throws OpenRoadmInterfaceException {
844         Mapping portMap = portMapping.getMapping(nodeId, logicalConnPoint);
845         if (portMap == null) {
846             throw new OpenRoadmInterfaceException(
847                 OpenRoadmInterfaceException.mapping_msg_err(nodeId, logicalConnPoint));
848         }
849         // Used to find if the port is regen-type
850         if (portMap.getXpdrType() == null) {
851             throw new OpenRoadmInterfaceException(
852                     OpenRoadmInterfaceException.mapping_xpdrtype_err(nodeId, logicalConnPoint));
853         }
854         // Set the ODUCn rate from OTUCn interface naming convention
855         String oducnrate = supportingOtucn.substring(supportingOtucn.length() - 1);
856         // check if the oducnrate is a valid value and if it is invalid, then throw error
857         if (!SUPPORTED_ODUCN_RATES.contains(oducnrate)) {
858             throw new OpenRoadmInterfaceException(RATE_EXCEPTION_MESSAGE);
859         }
860         // set the common parameters
861         OduBuilder oduBuilder = new OduBuilder()
862                 .setRate(ODUCn.VALUE)
863                 .setOducnNRate(Uint16.valueOf(oducnrate));
864
865         if (portMap.getXpdrType() == XpdrNodeTypes.Regen) {
866             LOG.info("Regen mode only supports not-terminated or monitored");
867             oduBuilder.setMonitoringMode(MonitoringMode.NotTerminated)
868                     .setOduFunction(ODUCTP.VALUE);
869         } else {
870             // if it is other than regen mode
871             oduBuilder.setMonitoringMode(MonitoringMode.Terminated)
872                     .setTimActEnabled(false)
873                     .setOduFunction(ODUTTP.VALUE)
874                     .setTimDetectMode(TimDetectMode.Disabled)
875                     .setDegmIntervals(Uint8.valueOf(2))
876                     .setDegthrPercentage(Uint16.valueOf(100))
877                     .setOducnNRate(Uint16.valueOf(oducnrate))
878                     .setOpu(
879                             // OPU payload
880                             new OpuBuilder()
881                                     .setExpPayloadType(PayloadTypeDef.getDefaultInstance("22"))
882                                     .setPayloadType(PayloadTypeDef.getDefaultInstance("22"))
883                                     .build());
884         }
885
886         InterfaceBuilder oduInterfaceBuilder =
887             createGenericInterfaceBuilder(portMap, OtnOdu.VALUE, logicalConnPoint + ODUC + oducnrate)
888                 .setSupportingInterfaceList(new HashSet<>(Set.of(supportingOtucn)))
889                 .addAugmentation(
890                     new org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.Interface1Builder()
891                         .setOdu(oduBuilder.build())
892                         .build());
893         // Post interface on the device
894         openRoadmInterfaces.postInterface(nodeId, oduInterfaceBuilder);
895         // Post the equipment-state change on the device circuit-pack if xpdr node
896         if (portMap.getLogicalConnectionPoint().contains(StringConstants.NETWORK_TOKEN)) {
897             this.openRoadmInterfaces.postEquipmentState(nodeId, portMap.getSupportingCircuitPackName(), true);
898         }
899         // Update the port-mapping with the interface information
900         this.portMapping.updateMapping(nodeId, portMap);
901         return oduInterfaceBuilder.getName();
902     }
903
904
905     // With SAPI and DAPI information
906     public String createOpenRoadmOtnOducnInterface(String anodeId, String alogicalConnPoint,
907             String supportingOtucn, String znodeId, String zlogicalConnPoint)
908             throws OpenRoadmInterfaceException {
909         Mapping portMapA = portMapping.getMapping(anodeId, alogicalConnPoint);
910         if (portMapA == null) {
911             throw new OpenRoadmInterfaceException(
912                 OpenRoadmInterfaceException.mapping_msg_err(anodeId, alogicalConnPoint));
913         }
914         if (portMapA.getXpdrType() == null) {
915             throw new OpenRoadmInterfaceException(
916                     OpenRoadmInterfaceException.mapping_xpdrtype_err(anodeId, alogicalConnPoint));
917         }
918         // On the Zside
919         Mapping portMapZ = portMapping.getMapping(znodeId, zlogicalConnPoint);
920         if (portMapZ == null) {
921             throw new OpenRoadmInterfaceException(
922                 OpenRoadmInterfaceException.mapping_msg_err(znodeId, zlogicalConnPoint));
923         }
924         // Set the ODUCn rate from OTUCn interface naming convention
925         String oducnrate = supportingOtucn.substring(supportingOtucn.length() - 1);
926         // check if the oducnrate is a valid value and if it is invalid, then throw error
927         if (!SUPPORTED_ODUCN_RATES.contains(oducnrate)) {
928             throw new OpenRoadmInterfaceException(RATE_EXCEPTION_MESSAGE);
929         }
930
931         // set the common parameters
932         OduBuilder oduBuilder = new OduBuilder()
933                 .setRate(ODUCn.VALUE)
934                 .setOducnNRate(Uint16.valueOf(oducnrate));
935
936         if (portMapA.getXpdrType() == XpdrNodeTypes.Regen) {
937             LOG.info("Regen mode only supports not-terminated or monitored");
938             oduBuilder.setMonitoringMode(MonitoringMode.NotTerminated)
939                     // For regen-mode ODU-function is set to CTP
940                     .setOduFunction(ODUCTP.VALUE);
941         } else {
942             // if it is other than regen mode
943             oduBuilder.setMonitoringMode(MonitoringMode.Terminated)
944                     .setTimActEnabled(false)
945                     .setOduFunction(ODUTTP.VALUE)
946                     .setTimDetectMode(TimDetectMode.Disabled)
947                     .setDegmIntervals(Uint8.valueOf(2))
948                     .setDegthrPercentage(Uint16.valueOf(100))
949                     .setOducnNRate(Uint16.valueOf(oducnrate))
950                     .setOpu(
951                             // OPU payload
952                             new OpuBuilder()
953                                     .setExpPayloadType(PayloadTypeDef.getDefaultInstance("22"))
954                                     .setPayloadType(PayloadTypeDef.getDefaultInstance("22"))
955                                     .build())
956                     .setTxSapi(portMapA.getLcpHashVal())
957                     .setTxDapi(portMapZ.getLcpHashVal())
958                     .setExpectedSapi(portMapZ.getLcpHashVal())
959                     .setExpectedDapi(portMapZ.getLcpHashVal());
960         }
961
962         InterfaceBuilder oduInterfaceBuilder =
963             createGenericInterfaceBuilder(portMapA, OtnOdu.VALUE, alogicalConnPoint + ODUC + oducnrate)
964                 .setSupportingInterfaceList(new HashSet<>(Set.of(supportingOtucn)))
965                 .addAugmentation(
966                     new org.opendaylight.yang.gen.v1.http.org.openroadm.otn.odu.interfaces.rev200529.Interface1Builder()
967                         .setOdu(oduBuilder.build())
968                         .build());
969         // Post interface on the device
970         openRoadmInterfaces.postInterface(anodeId, oduInterfaceBuilder);
971         // Post the equipment-state change on the device circuit-pack if xpdr node
972         if (portMapA.getLogicalConnectionPoint().contains(StringConstants.NETWORK_TOKEN)) {
973             this.openRoadmInterfaces.postEquipmentState(anodeId, portMapA.getSupportingCircuitPackName(), true);
974         }
975         // Update the port-mapping with the interface information
976         this.portMapping.updateMapping(anodeId, portMapA);
977         return oduInterfaceBuilder.getName();
978     }
979
980     // This creates the name of the interface with slot numbers at the end
981     public String createOpenRoadmOtsiInterfaceName(String logicalConnectionPoint, String spectralSlotName) {
982         return String.join(GridConstant.NAME_PARAMETERS_SEPARATOR, logicalConnectionPoint, spectralSlotName);
983     }
984
985     private InterfaceBuilder createGenericInterfaceBuilder(Mapping portMap, InterfaceType type, String key) {
986         return new org.opendaylight.yang.gen.v1.http.org.openroadm.device.rev200529.interfaces.grp.InterfaceBuilder()
987             .setDescription("  TBD   ")
988             .setCircuitId("   TBD    ")
989             .setSupportingCircuitPackName(portMap.getSupportingCircuitPackName())
990             .setSupportingPort(portMap.getSupportingPort())
991             .setAdministrativeState(AdminStates.InService)
992             .setType(type)
993             .setName(key)
994             .withKey(new InterfaceKey(key));
995     }
996
997     private int getServiceRate(ModulationFormat modulationFormat, SpectrumInformation spectrumInformation) {
998         switch (modulationFormat) {
999             case DpQpsk:
1000             case DpQam16:
1001                 // DpQpsk and DpQam16 are possible for both 31.6 or 63.1 GBaud, for which spectral width is different
1002                 // Here take the difference of highest and lowest spectral numbers and determine the width
1003                 double spectralWidth = (spectrumInformation.getHigherSpectralSlotNumber()
1004                     - spectrumInformation.getLowerSpectralSlotNumber() + 1) * GridConstant.GRANULARITY;
1005                 LOG.info("The width with guard band {}", spectralWidth);
1006                 if (spectralWidth == 50.0) {
1007                     LOG.info("The baud-rate is 31.6 GBaud");
1008                     return Map.of(
1009                             ModulationFormat.DpQpsk , 100,
1010                             ModulationFormat.DpQam16 , 200)
1011                         .get(modulationFormat);
1012                     // Based on roll-of-factor of 0.2, 50 - 12.5 = 37.5GHz translates to 31.6 GBaud
1013                 }
1014                 LOG.info("The baud-rate is 63.1 GBaud");
1015                 Map<ModulationFormat, Integer> rateMap = Map.of(
1016                         ModulationFormat.DpQpsk , 200,
1017                         ModulationFormat.DpQam16 , 400);
1018                 // Based on roll-of-factor of 0.2, 87.5 - 12.5 = 75GHz translates to 63.1 GBaud
1019                 int rate = rateMap.get(modulationFormat);
1020                 LOG.info("Given modulation format {} rate is {}", modulationFormat, rate);
1021                 return rate;
1022             case DpQam8:
1023                 LOG.info("Given modulation format DpQam8 rate is 300");
1024                 return 300;
1025             default:
1026                 LOG.error(RATE_EXCEPTION_MESSAGE + " for modulation format {}", modulationFormat);
1027                 return 0;
1028         }
1029     }
1030 }