blob: 8dd434c62b1807406e6e529627f78830cf771c5d [file] [log] [blame]
karthik1977bc5ea1e2023-01-02 19:25:14 +05301/*
2 * Copyright 2023-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.netflow.impl;
17
18import java.nio.ByteBuffer;
19import java.util.LinkedList;
20import java.util.List;
21import java.util.Objects;
22import java.util.function.BiPredicate;
23import java.util.function.Function;
24import java.util.function.Predicate;
25
26import com.google.common.base.MoreObjects;
27
28import org.onosproject.netflow.DataRecord;
29import org.onosproject.netflow.TemplateId;
30import org.onosproject.netflow.Flow;
31import org.onosproject.netflow.FlowTemplateField;
32import org.onosproject.netflow.DataDeserializer;
33
34import static com.google.common.base.Preconditions.checkNotNull;
35
36
37/**
38 * A Flow Data Record is a data record that contains values of the Flow.
39 * parameters corresponding to a Template Record.
40 * Ref: https://www.ietf.org/rfc/rfc3954.txt
41 */
42public class DataFlowRecord extends DataRecord {
43
44 /*
45 0 1 2 3
46 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
47 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48 | Record 1 - Field Value 1 | Record 1 - Field Value 2 |
49 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50 | Record 1 - Field Value 3 | ... |
51 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52 | Record 2 - Field Value 1 | Record 2 - Field Value 2 |
53 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54 | Record 2 - Field Value 3 | ... |
55 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56 */
57
58 private TemplateId templateId;
59
60 private List<Flow> flows;
61
62 public DataFlowRecord(Builder builder) {
63 this.templateId = builder.templateId;
64 this.flows = builder.flows;
65 }
66
67 /**
68 * Returns unique template ID.
69 * Template Records is given a unique Template ID.
70 * This uniqueness is local to the Observation
71 * Domain that generated the Template ID. Template IDs 0-255 are
72 * reserved for Template FlowSets, Options FlowSets, and other
73 * reserved FlowSets yet to be created.
74 *
75 * @return list of flowsets
76 */
77 @Override
78 public TemplateId getTemplateId() {
79 return this.templateId;
80 }
81
82 /**
83 * Returns type of data flow.
84 *
85 * @return type of data flow
86 */
87 public List<Flow> getFlows() {
88 return flows;
89 }
90
91 @Override
92 public int hashCode() {
93 int hash = 7;
94 hash = 29 * hash + Objects.hashCode(this.templateId);
95 hash = 29 * hash + Objects.hashCode(this.flows);
96 return hash;
97 }
98
99 @Override
100 public boolean equals(Object obj) {
101 if (this == obj) {
102 return true;
103 }
104 if (obj == null) {
105 return false;
106 }
107 if (getClass() != obj.getClass()) {
108 return false;
109 }
110 final DataFlowRecord other = (DataFlowRecord) obj;
111 if (!Objects.equals(this.templateId, other.templateId)) {
112 return false;
113 }
114 return Objects.equals(this.flows, other.flows);
115 }
116
117 @Override
118 public String toString() {
119 return MoreObjects.toStringHelper(getClass())
120 .add("templateId", templateId)
121 .add("flows", flows)
122 .toString();
123 }
124
125 /**
126 * Deserializer function for data flow record.
127 *
128 * @return deserializer function
129 */
130 public static DataDeserializer<DataFlowRecord> deserializer() {
131 return (data, offset, length, template) -> {
132 ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
133
134 Predicate<FlowTemplateField> isValidTemplate = t
135 -> Objects.nonNull(t) && Objects.nonNull(t.getFlowField()) && t.getLength() > 0;
136
137 BiPredicate<ByteBuffer, Integer> isValidBuffer = (b, l)
138 -> b.hasRemaining() && b.remaining() >= l;
139
140 Function<FlowTemplateField, Flow> parser = (f) -> {
141
142 if (!isValidTemplate.test(f) && isValidBuffer.test(bb, f.getLength())) {
143 throw new IllegalStateException("Invalid data set");
144 }
145 return new Flow.Builder()
146 .field(f.getFlowField())
147 .value(f.getFlowField().getParser().apply(bb, f.getLength()))
148 .build();
149
150 };
151 DataTemplateRecord templateRecord = (DataTemplateRecord) template;
152 Builder builder = new Builder()
153 .templateId(templateRecord.getTemplateId());
154 long count = templateRecord.getFields().stream()
155 .filter(Objects::nonNull)
156 .map(t -> builder.flow(parser.apply(t)))
157 .count();
158
159 if (count != templateRecord.getFiledCount()) {
160 throw new IllegalStateException("Invalid parsing fields");
161 }
162 return builder.build();
163 };
164 }
165
166 /**
167 * Builder for data flow record.
168 */
169 private static class Builder {
170
171 private TemplateId templateId;
172
173 private List<Flow> flows = new LinkedList<>();
174
175 /**
176 * Setter for unique template ID.
177 *
178 * @param templateId template id.
179 * @return this class builder.
180 */
181 public Builder templateId(TemplateId templateId) {
182 this.templateId = templateId;
183 return this;
184 }
185
186 /**
187 * Setter for data flow.
188 *
189 * @param flow data flow.
190 * @return this class builder.
191 */
192 public Builder flow(Flow flow) {
193 this.flows.add(flow);
194 return this;
195 }
196
197 /**
198 * Setter for list of data flow.
199 *
200 * @param flows list of data flow.
201 * @return this class builder.
202 */
203 public Builder flows(List<Flow> flows) {
204 this.flows = flows;
205 return this;
206 }
207
208 /**
209 * Checks arguments for data flow record.
210 */
211 private void checkArguments() {
212 checkNotNull(templateId, "TemplateId cannot be null");
213 }
214
215 /**
216 * Builds data flow record.
217 *
218 * @return data flow record.
219 */
220 public DataFlowRecord build() {
221 checkArguments();
222 return new DataFlowRecord(this);
223 }
224
225 }
226
227}