blob: d7bdd2669c7c23d55f32908a4e838cebfb6a8190 [file] [log] [blame]
Jonathan Hart3930f632015-10-19 12:12:51 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Jonathan Hart3930f632015-10-19 12:12:51 -07003 *
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 */
16
17package org.onosproject.routing.fpm.protocol;
18
19import com.google.common.base.MoreObjects;
20import org.onlab.packet.DeserializationException;
21
Kalhee Kimba366062017-11-07 16:32:09 +000022import org.jboss.netty.buffer.ChannelBuffer;
Jonathan Hart3930f632015-10-19 12:12:51 -070023import java.nio.ByteBuffer;
24
25import static org.onlab.packet.PacketUtils.checkInput;
26
27/**
28 * Netlink header.
29 * <p>
30 * Taken from struct nlmsghdr in linux/netlink.h
31 * </p>
32 */
33public final class Netlink {
34
35 public static final int NETLINK_HEADER_LENGTH = 16;
36
Kalhee Kimba366062017-11-07 16:32:09 +000037 public static final int NETLINK_REQUEST = 0x01;
38 public static final int NETLINK_CREATE = 0x400;
39
Jonathan Hart3930f632015-10-19 12:12:51 -070040 private final long length;
41 private final NetlinkMessageType type;
42 private final int flags;
43 private final long sequence;
44 private final long processPortId;
45
46 private final RtNetlink rtNetlink;
47
48 /**
49 * Class constructor.
50 *
51 * @param length message length
52 * @param type type
53 * @param flags flags
54 * @param sequence sequence number
55 * @param processPortId port ID
56 * @param rtNetlink netlink routing message
57 */
Kalhee Kim715dd732018-01-23 14:39:56 +000058 private Netlink(long length, NetlinkMessageType type, int flags, long sequence,
Jonathan Hart3930f632015-10-19 12:12:51 -070059 long processPortId, RtNetlink rtNetlink) {
60 this.length = length;
61 this.type = type;
62 this.flags = flags;
63 this.sequence = sequence;
64 this.processPortId = processPortId;
65 this.rtNetlink = rtNetlink;
66 }
67
68 /**
69 * Returns the message length.
70 *
71 * @return length
72 */
73 public long length() {
74 return length;
75 }
76
77 /**
78 * Returns the message type.
79 *
80 * @return message type
81 */
82 public NetlinkMessageType type() {
83 return type;
84 }
85
86 /**
87 * Returns the flags.
88 *
89 * @return flags
90 */
91 public int flags() {
92 return flags;
93 }
94
95 /**
96 * Returns the sequence number.
97 *
98 * @return sequence number
99 */
100 public long sequence() {
101 return sequence;
102 }
103
104 /**
105 * Returns the port ID.
106 *
107 * @return port ID
108 */
109 public long processPortId() {
110 return processPortId;
111 }
112
113 /**
114 * Returns the netlink routing message.
115 *
116 * @return netlink routing message
117 */
118 public RtNetlink rtNetlink() {
119 return rtNetlink;
120 }
121
122 @Override
123 public String toString() {
124 return MoreObjects.toStringHelper(getClass())
125 .add("length", length)
126 .add("type", type)
127 .add("flags", flags)
128 .add("sequence", sequence)
129 .add("processPortId", processPortId)
130 .add("rtNetlink", rtNetlink)
131 .toString();
132 }
133
134 /**
135 * Decodes a netlink header from an input buffer.
136 *
137 * @param buffer input buffer
138 * @param start starting position the netlink header
139 * @param length length of the message
140 * @return netlink header
141 * @throws DeserializationException if a netlink header could not be
142 * decoded from the input buffer
143 */
144 public static Netlink decode(byte[] buffer, int start, int length) throws
145 DeserializationException {
146 checkInput(buffer, start, length, NETLINK_HEADER_LENGTH);
147
148 ByteBuffer bb = ByteBuffer.wrap(buffer, start, length);
149
150 long messageLength = Integer.reverseBytes(bb.getInt());
151 int type = Short.reverseBytes(bb.getShort());
152 int flags = Short.reverseBytes(bb.getShort());
153 long sequence = Integer.reverseBytes(bb.getInt());
154 long processPortId = Integer.reverseBytes(bb.getInt());
155
156 NetlinkMessageType messageType = NetlinkMessageType.get(type);
157 if (messageType == null) {
158 throw new DeserializationException(
159 "Unsupported Netlink message type: " + type);
160 }
161
162 // Netlink messages from Quagga's FPM protocol are always in the
163 // netlink route family (family 0).
164 RtNetlink rtNetlink = RtNetlink.decode(buffer, bb.position(),
165 bb.limit() - bb.position());
166
167 return new Netlink(messageLength,
168 messageType,
169 flags,
170 sequence,
171 processPortId,
172 rtNetlink);
173 }
174
Kalhee Kimba366062017-11-07 16:32:09 +0000175 /**
176 * Encode the Netlink contents into the ChannelBuffer.
177 *
178 * @param cb channelbuffer to be filled in
179 */
180 public void encode(ChannelBuffer cb) {
181
182 cb.writeInt(Integer.reverseBytes((int) length));
183 cb.writeShort(Short.reverseBytes((short) type.type()));
184 cb.writeShort(Short.reverseBytes((short) flags));
185 cb.writeInt(Integer.reverseBytes((int) sequence));
186 cb.writeInt(Integer.reverseBytes((int) processPortId));
187
188 rtNetlink.encode(cb);
189 }
190
Kalhee Kim715dd732018-01-23 14:39:56 +0000191 /**
192 * Returns a new Netlink builder.
193 *
194 * @return Netlink builder
195 */
196 public static Builder builder() {
197 return new Builder();
198 }
199
200 /**
201 * Netlink Builder.
202 */
203 public static final class Builder {
204
205 private long length = 0;
206 private NetlinkMessageType type = NetlinkMessageType.RTM_NEWROUTE;
207 private int flags = 0;
208 private long sequence = 0;
209 private long processPortId = 0;
210 private RtNetlink rtNetlink = null;
211
212 /**
213 * Hide class constructor.
214 */
215 private Builder() {
216 }
217
218 /**
219 * Sets length for the Netlink that will be built.
220 *
221 * @param length to use for built Netlink
222 * @return this builder
223 */
224 public Builder length(long length) {
225 this.length = length;
226 return this;
227 }
228
229 /**
230 * Sets type for the Netlink that will be built.
231 *
232 * @param type to use for built Netlink
233 * @return this builder
234 */
235 public Builder type(NetlinkMessageType type) {
236 this.type = type;
237 return this;
238 }
239
240 /**
241 * Sets flags for the Netlink that will be built.
242 *
243 * @param flags to use for built Netlink
244 * @return this builder
245 */
246 public Builder flags(int flags) {
247 this.flags = flags;
248 return this;
249 }
250
251 /**
252 * Sets sequence for the Netlink that will be built.
253 *
254 * @param sequence to use for built Netlink
255 * @return this builder
256 */
257 public Builder sequence(long sequence) {
258 this.sequence = sequence;
259 return this;
260 }
261
262 /**
263 * Sets processPortId for the Netlink that will be built.
264 *
265 * @param processPortId to use for built Netlink
266 * @return this builder
267 */
268 public Builder processPortId(long processPortId) {
269 this.processPortId = processPortId;
270 return this;
271 }
272
273 /**
274 * Sets rtNetlink for the Netlink that will be built.
275 *
276 * @param rtNetlink to use for built Netlink
277 * @return this builder
278 */
279 public Builder rtNetlink(RtNetlink rtNetlink) {
280 this.rtNetlink = rtNetlink;
281 return this;
282 }
283
284 /**
285 * Builds the Netlink.
286 *
287 * @return Netlink reference
288 */
289 public Netlink build() {
290 return new Netlink(length, type, flags, sequence, processPortId, rtNetlink);
291 }
292 }
Jonathan Hart3930f632015-10-19 12:12:51 -0700293}