blob: be6ae9a3247e7a7c30e5ce5522b9dbbe9496cc4f [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 com.google.common.base.MoreObjects;
22import java.util.Objects;
23
24import org.onlab.packet.Deserializer;
25import org.onlab.packet.BasePacket;
26
27import static com.google.common.base.Preconditions.checkState;
28
29
30/**
31 * An Netflow Packet consists of a Packet Header followed by one or more
32 * FlowSets. The FlowSets can be any of the possible three types:
33 * Template, Data, or Options Template.
34 * Ref: https://www.ietf.org/rfc/rfc3954.txt
35 */
36public final class NetFlowPacket extends BasePacket {
37
38 /*
39 +--------+-------------------------------------------+
40 | | +----------+ +---------+ +----------+ |
41 | Packet | | Template | | Data | | Options | |
42 | Header | | FlowSet | | FlowSet | | Template | ... |
43 | | | | | | | FlowSet | |
44 | | +----------+ +---------+ +----------+ |
45 +--------+-------------------------------------------+
46
47 The Packet Header format is specified as:
48
49 0 1 2 3
50 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
51 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52 | Version Number | Count |
53 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54 | sysUpTime |
55 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56 | UNIX Secs |
57 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58 | Sequence Number |
59 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60 | Source ID |
61 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62
63*/
64
65
66 private int version;
67 private int count;
68 private long sysUptime;
69 private long timestamp;
70 private int flowSequence;
71 private int sourceId;
72 private List<FlowSet> flowSets;
73
74 private NetFlowPacket(Builder builder) {
75 this.version = builder.version;
76 this.count = builder.count;
77 this.sysUptime = builder.sysUptime;
78 this.timestamp = builder.timestamp;
79 this.flowSequence = builder.flowSequence;
80 this.sourceId = builder.sourceId;
81 this.flowSets = builder.flowSets;
82 }
83
84 /**
85 * Returns Version of Flow Record format exported in this packet.
86 *
87 * @return version number
88 */
89 public int getVersion() {
90 return version;
91 }
92
93 /**
94 * Returns total number of records in the Export Packet.
95 *
96 * @return total number of recoreds
97 */
98 public int getCount() {
99 return count;
100 }
101
102 /**
103 * Returns time in milliseconds since this device was first booted.
104 *
105 * @return system up time
106 */
107 public long getSysUptime() {
108 return sysUptime;
109 }
110
111 /**
112 * Returns packet timestamp.
113 * Time in seconds since 0000 UTC 1970, at which the Export Packet
114 * leaves the Exporter
115 *
116 * @return packet time stamp
117 */
118 public long getTimestamp() {
119 return timestamp;
120 }
121
122 /**
123 * Returns flow packet sequence number.
124 * Incremental sequence counter of all Export Packets sent from
125 * the current Observation Domain by the Exporter. This value
126 * MUST be cumulative, and SHOULD be used by the Collector to
127 * identify whether any Export Packets have been missed.
128 *
129 * @return packet sequence number
130 */
131 public int getFlowSequence() {
132 return flowSequence;
133 }
134
135 /**
136 * Returns A 32-bit value that identifies the Exporter Observation Domain.
137 *
138 * @return exporter source id
139 */
140 public int getSourceId() {
141 return sourceId;
142 }
143
144 /**
145 * Returns list of flowsets.
146 *
147 * @return list of flowsets
148 */
149 public List<FlowSet> getFlowSets() {
150 return flowSets;
151 }
152
153 /**
154 * Deserializer function for netflow packets.
155 *
156 * @return deserializer function
157 */
158 public static Deserializer<NetFlowPacket> deserializer() {
159 return (data, offset, length) -> {
160 System.out.println(length);
161 ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
162 Builder builder = new Builder();
163 builder.version(bb.getShort())
164 .count(bb.getShort())
165 .sysUptime(bb.getInt())
166 .timestamp(bb.getInt())
167 .flowSequence(bb.getInt())
168 .sourceId(bb.getInt());
169 while (bb.hasRemaining()) {
170
171 int flowSetId = bb.getShort();
172 int flowSetLength = bb.getShort();
173 bb.position(bb.position() - FlowSet.FLOW_SET_HEADER_LENTH);
174 byte[] flowSet;
175 if (bb.remaining() < flowSetLength) {
176 break;
177 }
178
179 flowSet = new byte[flowSetLength];
180 bb.get(flowSet);
181
182 builder.flowSet((FlowSet) FlowSet.Type.getType(flowSetId).getDecoder()
183 .deserialize(flowSet, 0, flowSetLength));
184 }
185 return builder.build();
186 };
187 }
188
189 @Override
190 public byte[] serialize() {
191 throw new UnsupportedOperationException("Not supported yet.");
192 }
193
194 @Override
195 public int hashCode() {
196 int hash = 3;
197 hash = 59 * hash + this.version;
198 hash = 59 * hash + this.count;
199 hash = 59 * hash + (int) (this.timestamp ^ (this.timestamp >>> 32));
200 hash = 59 * hash + this.flowSequence;
201 hash = 59 * hash + this.sourceId;
202 hash = 59 * hash + Objects.hashCode(this.flowSets);
203 return hash;
204 }
205
206 @Override
207 public boolean equals(Object obj) {
208 if (this == obj) {
209 return true;
210 }
211 if (obj == null) {
212 return false;
213 }
214 if (getClass() != obj.getClass()) {
215 return false;
216 }
217 final NetFlowPacket other = (NetFlowPacket) obj;
218 if (this.version != other.version) {
219 return false;
220 }
221 if (this.count != other.count) {
222 return false;
223 }
224 if (this.timestamp != other.timestamp) {
225 return false;
226 }
227 if (this.flowSequence != other.flowSequence) {
228 return false;
229 }
230 if (this.sourceId != other.sourceId) {
231 return false;
232 }
233 return Objects.equals(this.flowSets, other.flowSets);
234 }
235
236 @Override
237 public String toString() {
238 return MoreObjects.toStringHelper(getClass())
239 .add("version", version)
240 .add("count", count)
241 .add("sysUptime", sysUptime)
242 .add("timestamp", timestamp)
243 .add("flowSequence", flowSequence)
244 .add("sourceId", sourceId)
245 .add("flowSets", flowSets)
246 .toString();
247 }
248
249 /**
250 * Builder for netflow packet.
251 */
252 private static class Builder {
253
254 private int version;
255 private int count;
256 private long sysUptime;
257 private long timestamp;
258 private int flowSequence;
259 private int sourceId;
260 private List<FlowSet> flowSets = new LinkedList<>();
261
262 /**
263 * Setter Version of Flow Record format exported in this packet.
264 *
265 * @param version number.
266 * @return this class builder.
267 */
268 public Builder version(int version) {
269 this.version = version;
270 return this;
271 }
272
273 /**
274 * Setter for total number of records in the Export Packet.
275 *
276 * @param count flow record count.
277 * @return this class builder.
278 */
279 public Builder count(int count) {
280 this.count = count;
281 return this;
282 }
283
284 /**
285 * Setter for time in milliseconds since this device was first booted.
286 *
287 * @param sysUptime system up time.
288 * @return this class builder.
289 */
290 public Builder sysUptime(long sysUptime) {
291 this.sysUptime = sysUptime;
292 return this;
293 }
294
295 /**
296 * Setter for packet timestamp.
297 *
298 * @param timestamp packet timestamp.
299 * @return this class builder.
300 */
301 public Builder timestamp(long timestamp) {
302 this.timestamp = timestamp;
303 return this;
304 }
305
306 /**
307 * Setter for flow sequence.
308 *
309 * @param flowSequence flow sequence.
310 * @return this class builder.
311 */
312 public Builder flowSequence(int flowSequence) {
313 this.flowSequence = flowSequence;
314 return this;
315 }
316
317 /**
318 * Setter for sourceId.
319 *
320 * @param sourceId exporter sourceid.
321 * @return this class builder.
322 */
323 public Builder sourceId(int sourceId) {
324 this.sourceId = sourceId;
325 return this;
326 }
327
328 /**
329 * Setter for list of flowsets.
330 *
331 * @param flowSets list of flowsets.
332 * @return this class builder.
333 */
334 public Builder flowSets(List<FlowSet> flowSets) {
335 this.flowSets = flowSets;
336 return this;
337 }
338
339 /**
340 * Setter for flowset.
341 *
342 * @param flowSet flowset.
343 * @return this class builder.
344 */
345 public Builder flowSet(FlowSet flowSet) {
346 this.flowSets.add(flowSet);
347 return this;
348 }
349
350 /**
351 * Checks arguments for netflow packet.
352 */
353 private void checkArguments() {
354 checkState(version != 0, "Invalid Version.");
355 checkState(count != 0, "Invalid record count.");
356 checkState(sysUptime != 0, "Invalid system up time.");
357 checkState(timestamp != 0, "Invalid flow timestamp.");
358 }
359
360 /**
361 * Builds Netflow packet.
362 *
363 * @return Netflowpacket.
364 */
365 public NetFlowPacket build() {
366 checkArguments();
367 return new NetFlowPacket(this);
368 }
369
370 }
371
372}