blob: d454f1a9ece90d38d69ef2638427d6152455d1d6 [file] [log] [blame]
Rusty Eddy80f12522015-09-03 22:42:02 +00001/*
2 * Copyright 2015 Open Networking Laboratory
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.onlab.packet.pim;
17
18import org.onlab.packet.BasePacket;
19import org.onlab.packet.Deserializer;
20import org.onlab.packet.IPacket;
21import org.onlab.packet.IpAddress;
22
23import java.nio.ByteBuffer;
24import java.util.Random;
25
26import static org.onlab.packet.PacketUtils.checkInput;
27
28public class PIMHello extends BasePacket {
29
30 private IpAddress nbrIpAddress;
31
32 private int holdtime = 105;
33 private int genid = 0;
34 private int priority = 1;
35 private boolean priorityPresent = false;
36
37 public static final int MINIMUM_OPTION_LEN_BYTES = 4;
38
39 /**
40 * PIM Option types.
41 */
42 public enum Option {
43 HOLDTIME (1, 2),
44 PRUNEDELAY(2, 4),
45 PRIORITY (19, 4),
46 GENID (20, 4),
47 ADDRLIST (24, 0);
48
49 private final int optType;
50 private final int optLen;
51
52 Option(int ot, int ol) {
53 this.optType = ot;
54 this.optLen = ol;
55 }
56
57 public int optType() {
58 return this.optType;
59 }
60
61 public int optLen() {
62 return this.optLen;
63 }
64 }
65
66 /**
67 * Add the holdtime to the packet.
68 *
69 * @param holdtime the holdtime in seconds
70 */
71 public void addHoldtime(int holdtime) {
72 this.holdtime = holdtime;
73 }
74
75 /**
76 * Add the hello priority.
77 *
78 * @param priority default is 1, the higher the better
79 */
80 public void addPriority(int priority) {
81 this.priority = priority;
82 this.priorityPresent = true;
83 }
84
85 /**
86 * Add a Gen ID.
87 *
88 * @param genid a random generated number, changes only after reset.
89 */
90 public void addGenId(int genid) {
91 if (genid == 0) {
92 this.addGenId();
93 } else {
94 this.genid = genid;
95 }
96 }
97
98 /**
99 * Add the genid. Let this function figure out the number.
100 */
101 public void addGenId() {
102 Random rand = new Random();
103 this.genid = rand.nextInt();
104 }
105
106 /**
107 * Sets all payloads parent packet if applicable, then serializes this
108 * packet and all payloads.
109 *
110 * @return a byte[] containing this packet and payloads
111 */
112 @Override
113 public byte[] serialize() {
114
115 // TODO: Figure out a better way to calculate buffer size
116 int size = Option.PRIORITY.optLen() + 4 +
117 Option.GENID.optLen() + 4 +
118 Option.HOLDTIME.optLen() + 4;
119
120 byte[] data = new byte[size]; // Come up with something better
121 ByteBuffer bb = ByteBuffer.wrap(data);
122
123 // Add the priority
124 bb.putShort((short) Option.PRIORITY.optType);
125 bb.putShort((short) Option.PRIORITY.optLen);
126 bb.putInt(this.priority);
127
128 // Add the genid
129 bb.putShort((short) Option.GENID.optType);
130 bb.putShort((short) Option.GENID.optLen);
131 bb.putInt(this.genid);
132
133 // Add the holdtime
134 bb.putShort((short) Option.HOLDTIME.optType);
135 bb.putShort((short) Option.HOLDTIME.optLen);
136 bb.putShort((short) this.holdtime);
137 return data;
138 }
139
140 /**
141 * XXX: This is deprecated, DO NOT USE, use the deserializer() function instead.
142 */
143 // @Override
144 public IPacket deserialize(final byte[] data, final int offset,
145 final int length) {
146 //
147 return null;
148 }
149
150 /**
151 * Deserialize this hello message.
152 *
153 * @return a deserialized hello message.
154 */
155 public static Deserializer<PIMHello> deserializer() {
156 return (data, offset, length) -> {
157 checkInput(data, offset, length, MINIMUM_OPTION_LEN_BYTES);
158 final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
159
160 PIMHello hello = new PIMHello();
161 while (bb.hasRemaining()) {
162 int optType = bb.getShort();
163 int optLen = bb.getShort();
164
165 // Check that we have enough buffer for the next option.
166 checkInput(data, bb.position(), bb.limit() - bb.position(), optLen);
167 if (optType == Option.GENID.optType) {
168 hello.addGenId(bb.getInt());
169 } else if (optType == Option.PRIORITY.optType) {
170 hello.addPriority(bb.getInt());
171 } else if (optType == Option.HOLDTIME.optType) {
172 hello.addHoldtime((int) bb.getShort());
173 }
174 }
175
176 return hello;
177 };
178 }
179}