Added response data to operational datastore, refactored data validation
[packetcable.git] / packetcable-policy-server / src / main / java / org / opendaylight / controller / packetcable / provider / PCMMGateReqBuilder.java
1 /*
2  * Copyright (c) 2015 CableLabs 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.controller.packetcable.provider;
10
11 import java.net.Inet4Address;
12 import java.net.Inet6Address;
13 import java.net.InetAddress;
14 import java.net.UnknownHostException;
15 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151026.ServiceFlowDirection;
16 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151026.TosByte;
17 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151026.ccap.attributes.AmId;
18 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151026.pcmm.qos.classifier.Classifier;
19 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151026.pcmm.qos.ext.classifier.ExtClassifier;
20 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151026.pcmm.qos.gate.spec.GateSpec;
21 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151026.pcmm.qos.ipv6.classifier.Ipv6Classifier;
22 import org.opendaylight.yang.gen.v1.urn.packetcable.rev151026.pcmm.qos.traffic.profile.TrafficProfile;
23 import org.pcmm.gates.IClassifier;
24 import org.pcmm.gates.IClassifier.Protocol;
25 import org.pcmm.gates.IExtendedClassifier.ActivationState;
26 import org.pcmm.gates.IGateSpec.Direction;
27 import org.pcmm.gates.IIPv6Classifier.FlowLabel;
28 import org.pcmm.gates.ITrafficProfile;
29 import org.pcmm.gates.impl.AMID;
30 import org.pcmm.gates.impl.DOCSISServiceClassNameTrafficProfile;
31 import org.pcmm.gates.impl.GateID;
32 import org.pcmm.gates.impl.PCMMError;
33 import org.pcmm.gates.impl.PCMMGateReq;
34 import org.pcmm.gates.impl.SubscriberID;
35 import org.pcmm.gates.impl.TransactionID;
36 import org.slf4j.Logger;
37 import org.slf4j.LoggerFactory;
38
39 /**
40  * Build PCMM gate requests from API QoS Gate objects
41  */
42 public class PCMMGateReqBuilder {
43
44     private final Logger logger = LoggerFactory.getLogger(PCMMGateReqBuilder.class);
45
46     private GateID gateID = null;
47     private AMID amid = null;
48     private SubscriberID subscriberID = null;
49     private TransactionID transactionID = null;
50     private org.pcmm.gates.impl.GateSpec gateSpec = null;
51     private ITrafficProfile trafficProfile = null;
52     private IClassifier classifier = null;
53     private PCMMError error = null;
54
55     public PCMMGateReq build() {
56         return new PCMMGateReq(amid, subscriberID, transactionID, gateSpec, trafficProfile, classifier, gateID, error);
57     }
58
59     public void setAmId(final AmId qosAmId) {
60         amid = new AMID(qosAmId.getAmType().shortValue(), qosAmId.getAmTag().shortValue());
61     }
62
63     public void setSubscriberId(final InetAddress qosSubId) {
64         subscriberID = new SubscriberID(qosSubId);
65     }
66
67     public void setGateSpec(final GateSpec qosGateSpec, final ServiceFlowDirection scnDirection) {
68
69         final ServiceFlowDirection qosDir;
70         if (scnDirection != null) {
71             qosDir = scnDirection;
72         } else {
73             if (qosGateSpec.getDirection() != null) {
74                 qosDir = qosGateSpec.getDirection();
75             } else {
76                 // TODO - determine if this is a valid default value
77                 qosDir = ServiceFlowDirection.Ds;
78             }
79         }
80
81         final Direction gateDir;
82         if (qosDir == ServiceFlowDirection.Ds) {
83             gateDir = Direction.DOWNSTREAM;
84         } else {
85             gateDir = Direction.UPSTREAM;
86         }
87
88         // DSCP/TOS Overwrite
89         final byte dscptos;
90         final byte gateTosMask;
91
92         final TosByte tosOverwrite = qosGateSpec.getDscpTosOverwrite();
93         if (tosOverwrite != null) {
94             dscptos = 1;
95             TosByte tosMask = qosGateSpec.getDscpTosMask();
96             if (tosMask != null) {
97                 gateTosMask = tosMask.getValue().byteValue();
98             } else {
99                 gateTosMask = (byte) 0xff;
100             }
101         } else {
102             // TODO - These values appear to be required
103             dscptos = 0;
104             gateTosMask = 0;
105         }
106         gateSpec = new org.pcmm.gates.impl.GateSpec(gateDir, dscptos, gateTosMask);
107     }
108
109     public void setTrafficProfile(final TrafficProfile qosTrafficProfile) {
110         if (qosTrafficProfile.getServiceClassName() != null) {
111             trafficProfile =
112                     new DOCSISServiceClassNameTrafficProfile(qosTrafficProfile.getServiceClassName().getValue());
113         }
114     }
115
116     private InetAddress getByName(final String ipAddressStr) {
117         try {
118             return InetAddress.getByName(ipAddressStr);
119         } catch (UnknownHostException e) {
120             logger.error(e.getMessage());
121         }
122         return null;
123     }
124
125     public void setClassifier(final Classifier qosClassifier) {
126         // TODO - try and make these variables immutable
127         Protocol protocol = null;
128         byte tosOverwrite = 0;
129         byte tosMask = (byte)0x0;
130         Inet4Address srcAddress = null;
131         Inet4Address dstAddress = null;
132         short srcPort = (short) 0;
133         short dstPort = (short) 0;
134         byte priority = (byte) 64;
135
136         // Legacy classifier
137         if (qosClassifier.getProtocol() != null) {
138             protocol = Protocol.valueOf(qosClassifier.getProtocol().getValue().shortValue());
139         }
140         if (qosClassifier.getSrcIp() != null) {
141             final InetAddress sip = getByName(qosClassifier.getSrcIp().getValue());
142             if (sip != null && sip instanceof Inet4Address) {
143                 srcAddress = (Inet4Address) sip;
144             }
145         }
146         if (qosClassifier.getDstIp() != null) {
147             final InetAddress dip = getByName(qosClassifier.getDstIp().getValue());
148             if (dip != null && dip instanceof Inet4Address) {
149                 dstAddress = (Inet4Address) dip;
150             }
151         }
152         if (qosClassifier.getSrcPort() != null) {
153             srcPort = qosClassifier.getSrcPort().getValue().shortValue();
154         }
155         if (qosClassifier.getDstPort() != null) {
156             dstPort = qosClassifier.getDstPort().getValue().shortValue();
157         }
158         if (qosClassifier.getTosByte() != null) {
159             tosOverwrite = qosClassifier.getTosByte().getValue().byteValue();
160             if (qosClassifier.getTosMask() != null) {
161                 tosMask = qosClassifier.getTosMask().getValue().byteValue();
162             } else {
163                 // set default TOS mask
164                 tosMask = (byte) 0xff;
165             }
166         }
167         // push the classifier to the gate request
168         classifier =
169                 new org.pcmm.gates.impl.Classifier(protocol, tosOverwrite, tosMask, srcAddress, dstAddress, srcPort,
170                         dstPort, priority);
171     }
172
173     public void setExtClassifier(final ExtClassifier qosExtClassifier) {
174         // Extended classifier
175         final byte priority = (byte) 64;
176         final ActivationState activationState = ActivationState.ACTIVE;
177         // Protocol -- zero is match any
178         final Protocol protocol;
179         if (qosExtClassifier.getProtocol() != null) {
180             protocol = Protocol.valueOf(qosExtClassifier.getProtocol().getValue().shortValue());
181         } else {
182             protocol = Protocol.NONE;
183         }
184
185         // default source port range must be set to match any even if qosExtClassifier has no range
186         // match any port range is 0-65535, NOT 0-0
187         // TODO - try to make these two variables immutable
188         short srcStartPort = (short) 0;
189         short srcEndPort = (short) 65535;
190         if (qosExtClassifier.getSrcPortStart() != null) {
191             srcStartPort = qosExtClassifier.getSrcPortStart().getValue().shortValue();
192             srcEndPort = srcStartPort;
193             if (qosExtClassifier.getSrcPortEnd() != null) {
194                 srcEndPort = qosExtClassifier.getSrcPortEnd().getValue().shortValue();
195             }
196             if (srcStartPort > srcEndPort) {
197                 logger.warn("Start port %d > End port %d in ext-classifier source port range -- forcing to same",
198                         srcStartPort, srcEndPort);
199                 srcEndPort = srcStartPort;
200             }
201         }
202         // default destination port range must be set to match any even if qosExtClassifier has no range
203         // match any port range is 0-65535, NOT 0-0
204         // TODO - try to make these two variables immutable
205         short dstStartPort = (short) 0;
206         short dstEndPort = (short) 65535;
207         if (qosExtClassifier.getDstPortStart() != null) {
208             dstStartPort = qosExtClassifier.getDstPortStart().getValue().shortValue();
209             dstEndPort = dstStartPort;
210             if (qosExtClassifier.getDstPortEnd() != null) {
211                 dstEndPort = qosExtClassifier.getDstPortEnd().getValue().shortValue();
212             }
213             if (dstStartPort > dstEndPort) {
214                 logger.warn("Start port %d > End port %d in ext-classifier destination port range -- forcing to same",
215                         dstStartPort, dstEndPort);
216                 dstEndPort = dstStartPort;
217             }
218         }
219
220         // DSCP/TOP byte
221         // TODO - try to make these two variables immutable
222         byte tosOverwrite = 0;
223         byte tosMask = (byte)0x00;
224         if (qosExtClassifier.getTosByte() != null) {
225             // OR in the DSCP/TOS enable bit 0x01
226             tosOverwrite = (byte) (qosExtClassifier.getTosByte().getValue().byteValue() | 0x01);
227             if (qosExtClassifier.getTosMask() != null) {
228                 tosMask = qosExtClassifier.getTosMask().getValue().byteValue();
229             } else {
230                 // set default TOS mask
231                 tosMask = (byte) 0xff;
232             }
233         }
234
235         // TODO - find out what the classifier ID should really be. It was never getting set previously
236         final short classifierId = (short)0;
237
238         // TODO - find out what the action value should really be. It was never getting set previously
239         final byte action = (byte)0;
240
241         // push the extended classifier to the gate request
242         classifier = new org.pcmm.gates.impl.ExtendedClassifier(protocol, tosOverwrite, tosMask,
243                 getInet4Address(qosExtClassifier.getSrcIp()), getInet4Address(qosExtClassifier.getDstIp()),
244                 srcStartPort, dstStartPort, priority, getInet4Address(qosExtClassifier.getSrcIpMask()),
245                 getInet4Address(qosExtClassifier.getDstIpMask()), srcEndPort, dstEndPort, classifierId, activationState,
246                 action);
247     }
248
249     private Inet4Address getInet4Address(
250             final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address address) {
251         if (address != null) {
252             final InetAddress out = getByName(address.getValue());
253             if (out != null && out instanceof Inet4Address) {
254                 return (Inet4Address) out;
255             }
256         }
257         return null;
258     }
259
260     public void setIpv6Classifier(final Ipv6Classifier qosIpv6Classifier) {
261         // Next Header
262         final short nextHdr;
263         if (qosIpv6Classifier.getNextHdr() != null) {
264             nextHdr = qosIpv6Classifier.getNextHdr().getValue().shortValue();
265         }
266         // default: match any nextHdr is 256 because nextHdr 0 is Hop-by-Hop option
267         else {
268             nextHdr = (short) 256;
269         }
270
271         // Source IPv6 address & prefix len
272         // TODO - try to make these two variables immutable
273         byte srcPrefixLen = (byte) 128;
274         Inet6Address srcAddress = null;
275         if (qosIpv6Classifier.getSrcIp6() != null) {
276             String[] parts = qosIpv6Classifier.getSrcIp6().getValue().split("/");
277             String Ipv6AddressStr = parts[0];
278             srcAddress = (Inet6Address) getByName(Ipv6AddressStr);
279             if (parts.length > 1) {
280                 srcPrefixLen = (byte) Integer.parseInt(parts[1]);
281             } else {
282                 srcPrefixLen = (byte) 128;
283             }
284
285         }
286
287         // TODO - try to make these two variables immutable
288         Inet6Address dstAddress = null;
289         byte dstPrefLen = (byte) 128;
290         // Destination IPv6 address & prefix len
291         if (qosIpv6Classifier.getDstIp6() != null) {
292             final String[] parts = qosIpv6Classifier.getDstIp6().getValue().split("/");
293             final String Ipv6AddressStr = parts[0];
294             dstAddress = (Inet6Address)getByName(Ipv6AddressStr);
295             if (parts.length > 1) dstPrefLen = (byte) Integer.parseInt(parts[1]);
296             else dstPrefLen = (byte) 128;
297         }
298
299         // default source port range must be set to match any -- even if qosExtClassifier has no range value
300         // match any port range is 0-65535, NOT 0-0
301         short srcPortBegin = (short) 0;
302         short srcPortEnd = (short) 65535;
303         if (qosIpv6Classifier.getSrcPortStart() != null) {
304             srcPortBegin = qosIpv6Classifier.getSrcPortStart().getValue().shortValue();
305             srcPortEnd = srcPortBegin;
306             if (qosIpv6Classifier.getSrcPortEnd() != null) {
307                 srcPortEnd = qosIpv6Classifier.getSrcPortEnd().getValue().shortValue();
308             }
309             if (srcPortBegin > srcPortEnd) {
310                 logger.warn("Start port %d > End port %d in ipv6-classifier source port range -- forcing to same",
311                         srcPortBegin, srcPortEnd);
312                 srcPortEnd = srcPortBegin;
313             }
314         }
315
316         // default destination port range must be set to match any -- even if qosExtClassifier has no range value
317         // match any port range is 0-65535, NOT 0-0
318         short dstPortBegin = (short) 0;
319         short dstPortEnd = (short) 65535;
320         if (qosIpv6Classifier.getDstPortStart() != null) {
321             dstPortBegin = qosIpv6Classifier.getDstPortStart().getValue().shortValue();
322             dstPortEnd = dstPortBegin;
323             if (qosIpv6Classifier.getDstPortEnd() != null) {
324                 dstPortEnd = qosIpv6Classifier.getDstPortEnd().getValue().shortValue();
325             }
326             if (dstPortBegin > dstPortEnd) {
327                 logger.warn("Start port %d > End port %d in ipv6-classifier destination port range -- forcing to same",
328                         dstPortBegin, dstPortEnd);
329                 dstPortEnd = dstPortBegin;
330             }
331         }
332
333         final byte tcLow;
334         if (qosIpv6Classifier.getTcLow() != null)
335             tcLow = qosIpv6Classifier.getTcLow().getValue().byteValue();
336         else tcLow = (byte) 0x00;
337
338         final byte tcHigh;
339         if (qosIpv6Classifier.getTcHigh() != null)
340             tcHigh = qosIpv6Classifier.getTcHigh().getValue().byteValue();
341         else tcHigh = (byte) 0x00;
342
343         final byte tcMask;
344         if (qosIpv6Classifier.getTcHigh() != null)
345             tcMask = qosIpv6Classifier.getTcHigh().getValue().byteValue();
346         else if (qosIpv6Classifier.getTcLow() != null) tcMask = (byte) 0xff;
347         else tcMask = (byte) 0x00;
348
349         // TODO - find out what the classifier ID should really be. It was never getting set previously
350         final short classifierId = (short)0;
351
352         // TODO - find out what the action value should really be. It was never getting set previously
353         final byte action = (byte)0;
354
355         // push the IPv6 classifier to the gate request
356         classifier = new org.pcmm.gates.impl.IPv6Classifier(srcAddress, dstAddress, srcPortBegin, dstPortBegin,
357                 (byte) 64, srcPortEnd, dstPortEnd, classifierId, ActivationState.ACTIVE, action, FlowLabel.VALID, tcLow,
358                 tcHigh, tcMask, qosIpv6Classifier.getFlowLabel().intValue(), nextHdr, srcPrefixLen, dstPrefLen);
359     }
360 }