Path Computation Server
[bgpcep.git] / pcep / server / server-provider / src / main / java / org / opendaylight / bgpcep / pcep / server / provider / MessagesUtil.java
1 /*
2  * Copyright (c) 2020 Orange.  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.bgpcep.pcep.server.provider;
10
11 import com.google.common.collect.Lists;
12 import java.nio.ByteBuffer;
13 import java.util.ArrayList;
14 import java.util.Collections;
15 import java.util.List;
16 import org.eclipse.jdt.annotation.NonNull;
17 import org.opendaylight.protocol.pcep.spi.PCEPErrors;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6AddressNoZone;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ieee754.rev130819.Float32;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.Bandwidth;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev200120.ConstrainedPath;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.path.computation.rev200120.path.descriptions.PathDescription;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev181109.Pcerr;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev181109.PcerrBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev181109.Pcrep;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.message.rev181109.PcrepBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev181109.SidType;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev181109.pcrep.pcrep.message.replies.result.success._case.success.paths.ero.subobject.subobject.type.SrEroType;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev181109.pcrep.pcrep.message.replies.result.success._case.success.paths.ero.subobject.subobject.type.SrEroTypeBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.segment.routing.rev181109.sr.subobject.nai.IpNodeIdBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.NoPathVectorTlv.Flags;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.RequestId;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.bandwidth.object.BandwidthBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.classtype.object.ClassTypeBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.explicit.route.object.Ero;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.explicit.route.object.EroBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.explicit.route.object.ero.Subobject;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.explicit.route.object.ero.SubobjectBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lsp.attributes.Metrics;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.lsp.attributes.MetricsBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.metric.object.MetricBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcep.error.object.ErrorObjectBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcerr.message.PcerrMessageBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcerr.message.pcerr.message.ErrorsBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcerr.message.pcerr.message.error.type.RequestCaseBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcerr.message.pcerr.message.error.type.request._case.RequestBuilder;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcerr.message.pcerr.message.error.type.request._case.request.RpsBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.PcrepMessageBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.RepliesBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.FailureCaseBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.SuccessCaseBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.failure._case.NoPathBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.failure._case.no.path.TlvsBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.failure._case.no.path.tlvs.NoPathVectorBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.success._case.SuccessBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.success._case.success.Paths;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcrep.message.pcrep.message.replies.result.success._case.success.PathsBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.pcreq.message.pcreq.message.requests.segment.computation.P2p;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.rp.object.Rp;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109.rp.object.RpBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.basic.explicit.route.subobjects.subobject.type.IpPrefixCase;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.basic.explicit.route.subobjects.subobject.type.IpPrefixCaseBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.basic.explicit.route.subobjects.subobject.type.ip.prefix._case.IpPrefix;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.rsvp.rev150820.basic.explicit.route.subobjects.subobject.type.ip.prefix._case.IpPrefixBuilder;
69 import org.opendaylight.yangtools.yang.common.Uint32;
70 import org.opendaylight.yangtools.yang.common.Uint8;
71
72 public final class MessagesUtil {
73
74     public static final byte NO_PATH = 0x0;
75     public static final byte UNKNOWN_SOURCE = 0x1;
76     public static final byte UNKNOWN_DESTINATION = 0x0;
77
78     /*
79      * See
80      * https://www.iana.org/assignments/pcep/pcep.xhtml#metric-object-ni-field
81      */
82     public static final int IGP_METRIC = 1;
83     public static final int TE_METRIC = 2;
84     public static final int PATH_DELAY = 12;
85
86     private MessagesUtil() {
87         throw new UnsupportedOperationException();
88     }
89
90     public static Ero getEro(List<PathDescription> pathDescriptions) {
91         /* Prepare ERO */
92         final EroBuilder eroBuilder = new EroBuilder();
93         eroBuilder.setIgnore(false);
94         eroBuilder.setProcessingRule(true);
95         final List<Subobject> eroSubs = new ArrayList<>();
96
97         /* Fulfill ERO sublist */
98         for (PathDescription path : pathDescriptions) {
99             Subobject sb = null;
100             if (path.getLabel() == null) {
101                 IpPrefix ipPref = null;
102                 /* Prepare SubObject for IPv4 or IPv6 address */
103                 if (path.getIpv4() != null) {
104                     final Ipv4Prefix ipv4Pref = new Ipv4Prefix(path.getIpv4().getValue() + "/32");
105                     ipPref = new IpPrefixBuilder().setIpPrefix(
106                             new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715
107                                     .IpPrefix(ipv4Pref))
108                             .build();
109                 }
110                 if (path.getIpv6() != null) {
111                     final Ipv6Prefix ipv6Pref = new Ipv6Prefix(path.getIpv6().getValue() + "/128");
112                     ipPref = new IpPrefixBuilder().setIpPrefix(
113                             new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715
114                                     .IpPrefix(ipv6Pref))
115                             .build();
116                 }
117                 if (ipPref != null) {
118                     final IpPrefixCase ipPrefCase = new IpPrefixCaseBuilder().setIpPrefix(ipPref).build();
119                     sb = new SubobjectBuilder().setSubobjectType(ipPrefCase).setLoose(false).build();
120                 }
121             } else {
122                 /* Prepare SubObject for Segment Routing */
123                 SrEroType srEro = null;
124                 if (path.getIpv4() != null) {
125                     srEro = new SrEroTypeBuilder()
126                             .setSidType(SidType.Ipv4NodeId)
127                             .setSid(path.getLabel().getValue())
128                             .setCFlag(false)
129                             .setMFlag(false)
130                             .setNai(new IpNodeIdBuilder()
131                                     .setIpAddress(new IpAddressNoZone(new Ipv4AddressNoZone(path.getIpv4().getValue())))
132                                     .build())
133                             .build();
134                 }
135                 if (path.getIpv6() != null) {
136                     srEro = new SrEroTypeBuilder()
137                             .setSidType(SidType.Ipv6NodeId)
138                             .setSid(path.getLabel().getValue())
139                             .setCFlag(false)
140                             .setMFlag(false)
141                             .setNai(new IpNodeIdBuilder()
142                                     .setIpAddress(new IpAddressNoZone(new Ipv6AddressNoZone(path.getIpv6().getValue())))
143                                     .build())
144                             .build();
145                 }
146                 if (srEro != null) {
147                     sb = new SubobjectBuilder().setSubobjectType(srEro).setLoose(false).build();
148                 }
149             }
150
151             /* Add corresponding SubObject to the ERO List */
152             if (sb != null) {
153                 eroSubs.add(sb);
154             }
155         }
156         /* Set ERO sublist */
157         eroBuilder.setSubobject(eroSubs);
158
159         return eroBuilder.build();
160     }
161
162     private static PathsBuilder buildPath(ConstrainedPath cpath) {
163         final PathsBuilder pathBuilder = new PathsBuilder();
164
165         /* Get ERO from Path Description */
166         pathBuilder.setEro(getEro(cpath.getPathDescription()));
167
168         /* Fulfill Computed Metrics if available */
169         final ArrayList<Metrics> metrics = new ArrayList<Metrics>();
170         if (cpath.getMetric() != null) {
171             final MetricBuilder metricBuilder = new MetricBuilder().setComputed(true)
172                     .setMetricType(Uint8.valueOf(IGP_METRIC)).setValue(new Float32(
173                             ByteBuffer.allocate(4).putFloat(Float.valueOf(cpath.getMetric().floatValue())).array()));
174             metrics.add(new MetricsBuilder().setMetric(metricBuilder.build()).build());
175         }
176         if (cpath.getTeMetric() != null) {
177             final MetricBuilder metricBuilder = new MetricBuilder().setComputed(true)
178                     .setMetricType(Uint8.valueOf(TE_METRIC)).setValue(new Float32(
179                             ByteBuffer.allocate(4).putFloat(Float.valueOf(cpath.getTeMetric().floatValue())).array()));
180             metrics.add(new MetricsBuilder().setMetric(metricBuilder.build()).build());
181         }
182         if (cpath.getDelay() != null) {
183             final MetricBuilder metricBuilder = new MetricBuilder().setComputed(true)
184                     .setMetricType(Uint8.valueOf(PATH_DELAY)).setValue(new Float32(ByteBuffer.allocate(4)
185                             .putFloat(Float.valueOf(cpath.getDelay().getValue().floatValue())).array()));
186             metrics.add(new MetricsBuilder().setMetric(metricBuilder.build()).build());
187         }
188         if (!metrics.isEmpty()) {
189             pathBuilder.setMetrics(metrics);
190         }
191         /* Fulfill Bandwidth and ClassType if set */
192         if (cpath.getBandwidth() != null) {
193             final BandwidthBuilder bwBuilder = new BandwidthBuilder();
194             bwBuilder.setBandwidth(new Bandwidth(new Float32(ByteBuffer.allocate(4)
195                     .putFloat(Float.valueOf(cpath.getBandwidth().getValue().floatValue())).array())));
196             pathBuilder.setBandwidth(bwBuilder.build());
197             if (cpath.getClassType() != null) {
198                 pathBuilder.setClassType(new ClassTypeBuilder().setClassType(
199                         new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev181109
200                                 .ClassType(cpath.getClassType()))
201                         .build());
202             }
203         }
204         return pathBuilder;
205     }
206
207     public static Pcrep createPcRepMessage(Rp rp, P2p p2p, ConstrainedPath cpath) {
208
209         /* Prepare Path Object with ERO and Object from the Request */
210         final ArrayList<Paths> paths = new ArrayList<Paths>();
211         PathsBuilder pathBuilder = buildPath(cpath);
212
213         if (p2p.getLspa() != null) {
214             pathBuilder.setLspa(p2p.getLspa());
215         }
216         if (p2p.getIro() != null) {
217             pathBuilder.setIro(p2p.getIro());
218         }
219         if (p2p.getXro() != null) {
220             pathBuilder.setXro(p2p.getXro());
221         }
222         paths.add(pathBuilder.build());
223
224         /* Prepare Reply with Path Object */
225         final RepliesBuilder replyBuilder = new RepliesBuilder()
226                 .setRp(rp)
227                 .setResult(new SuccessCaseBuilder().setSuccess(new SuccessBuilder().setPaths(paths).build()).build());
228
229         /* Prepare PcRep Message */
230         final PcrepMessageBuilder msgBuilder = new PcrepMessageBuilder()
231                 .setReplies(Lists.newArrayList(replyBuilder.build()));
232         return new PcrepBuilder().setPcrepMessage(msgBuilder.build()).build();
233     }
234
235     public static Pcrep createNoPathMessage(Rp rp, byte reason) {
236
237         /* Prepare NoPath Object */
238         final Flags flags = new Flags(false, false, false, false, false, false,
239                 (reason == UNKNOWN_DESTINATION) ? true : false, (reason == UNKNOWN_SOURCE) ? true : false);
240         final NoPathVectorBuilder npvBuilder = new NoPathVectorBuilder().setFlags(flags);
241         final TlvsBuilder tlvsBuilder = new TlvsBuilder().setNoPathVector(npvBuilder.build());
242         final NoPathBuilder npBuilder = new NoPathBuilder()
243                 .setProcessingRule(false)
244                 .setIgnore(false)
245                 .setNatureOfIssue(Uint8.ZERO)
246                 .setUnsatisfiedConstraints(true)
247                 .setTlvs(tlvsBuilder.build());
248
249         /* Prepare Reply */
250         final RepliesBuilder replyBuilder = new RepliesBuilder()
251                 .setRp(rp)
252                 .setResult(new FailureCaseBuilder().setNoPath(npBuilder.build()).build());
253
254         /* Prepare PcRep Message */
255         final PcrepMessageBuilder msgBuilder = new PcrepMessageBuilder()
256                 .setReplies(Lists.newArrayList(replyBuilder.build()));
257         return new PcrepBuilder().setPcrepMessage(msgBuilder.build()).build();
258     }
259
260     public static Pcerr createErrorMsg(@NonNull final PCEPErrors pcepErrors, final Uint32 reqID) {
261         final PcerrMessageBuilder msgBuilder = new PcerrMessageBuilder();
262         return new PcerrBuilder().setPcerrMessage(msgBuilder
263                 .setErrorType(
264                         new RequestCaseBuilder().setRequest(new RequestBuilder()
265                                 .setRps(Lists
266                                         .newArrayList(new RpsBuilder().setRp(new RpBuilder().setProcessingRule(false)
267                                                 .setIgnore(false).setRequestId(new RequestId(reqID)).build()).build()))
268                                 .build()).build())
269                 .setErrors(Collections.singletonList(new ErrorsBuilder().setErrorObject(new ErrorObjectBuilder()
270                         .setType(pcepErrors.getErrorType()).setValue(pcepErrors.getErrorValue()).build()).build()))
271                 .build()).build();
272     }
273
274 }