blob: ef2faa4a3c5276f20181b74f50af8bc0eed37e8e [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 com.google.common.collect.ImmutableList;
21import org.onlab.packet.DeserializationException;
22
23import java.nio.ByteBuffer;
24import java.util.ArrayList;
25import java.util.List;
Kalhee Kimba366062017-11-07 16:32:09 +000026import org.jboss.netty.buffer.ChannelBuffer;
Jonathan Hart3930f632015-10-19 12:12:51 -070027
28import static org.onlab.packet.PacketUtils.checkInput;
29
30/**
31 * Netlink routing message (rtnetlink).
32 * <p>
33 * Taken from struct rtmsg in linux/rtnetlink.h
34 * </p>
35 */
36public final class RtNetlink {
37
Kalhee Kimba366062017-11-07 16:32:09 +000038 public static final int RT_ADDRESS_FAMILY_INET = 2;
39 public static final int RT_ADDRESS_FAMILY_INET6 = 10;
40 public static final int RT_NETLINK_LENGTH = 12;
Jonathan Hart3930f632015-10-19 12:12:51 -070041
42 private static final int MASK = 0xff;
43
44 private final short addressFamily;
45 private final int dstLength;
46 private final int srcLength;
47 private final short tos;
48 private final short table;
Jonathan Hart916bf892016-01-27 16:42:55 -080049 private final RtProtocol protocol;
Jonathan Hart3930f632015-10-19 12:12:51 -070050 private final short scope;
51 private final short type;
52 private final long flags;
53
54 private final List<RouteAttribute> attributes;
55
56 /**
57 * Class constructor.
58 *
59 * @param addressFamily address family
60 * @param dstLength destination address length
61 * @param srcLength source address length
62 * @param tos type of service
63 * @param table routing table
64 * @param protocol protocol
65 * @param scope scope
66 * @param type type
67 * @param flags flags
68 * @param attributes list of attributes
69 */
Kalhee Kim715dd732018-01-23 14:39:56 +000070 private RtNetlink(short addressFamily,
Jonathan Hart3930f632015-10-19 12:12:51 -070071 int dstLength,
72 int srcLength,
73 short tos,
74 short table,
Jonathan Hart916bf892016-01-27 16:42:55 -080075 RtProtocol protocol,
Jonathan Hart3930f632015-10-19 12:12:51 -070076 short scope,
77 short type,
78 long flags,
79 List<RouteAttribute> attributes) {
80
81 this.addressFamily = addressFamily;
82 this.dstLength = dstLength;
83 this.srcLength = srcLength;
84 this.tos = tos;
85 this.table = table;
86 this.protocol = protocol;
87 this.scope = scope;
88 this.type = type;
89 this.flags = flags;
90
91 this.attributes = ImmutableList.copyOf(attributes);
92
93 }
94
95 /**
96 * Returns the address family of the route.
97 *
98 * @return address family
99 */
100 public short addressFamily() {
101 return addressFamily;
102 }
103
104 /**
105 * Returns the destination address length.
106 *
107 * @return destination address length
108 */
109 public int dstLength() {
110 return dstLength;
111 }
112
113 /**
114 * Returns the source address length.
115 *
116 * @return source address length
117 */
118 public int srcLength() {
119 return srcLength;
120 }
121
122 /**
123 * Returns the type of service.
124 *
125 * @return type of service
126 */
127 public short tos() {
128 return tos;
129 }
130
131 /**
132 * Returns the routing table.
133 *
134 * @return routing table
135 */
136 public short table() {
137 return table;
138 }
139
140 /**
141 * Returns the protocol.
142 *
143 * @return protocol
144 */
Jonathan Hart916bf892016-01-27 16:42:55 -0800145 public RtProtocol protocol() {
Jonathan Hart3930f632015-10-19 12:12:51 -0700146 return protocol;
147 }
148
149 /**
150 * Returns the route scope.
151 *
152 * @return scope
153 */
154 public short scope() {
155 return scope;
156 }
157
158 /**
159 * Returns the route type.
160 *
161 * @return route type
162 */
163 public short type() {
164 return type;
165 }
166
167 /**
168 * Returns the route flags.
169 *
170 * @return route flags
171 */
172 public long flags() {
173 return flags;
174 }
175
176 /**
177 * Returns the list of route attributes.
178 *
179 * @return route attributes
180 */
181 public List<RouteAttribute> attributes() {
182 return attributes;
183 }
184
185 @Override
186 public String toString() {
187 return MoreObjects.toStringHelper(getClass())
188 .add("addressFamily", addressFamily)
189 .add("dstLength", dstLength)
190 .add("srcLength", srcLength)
191 .add("tos", tos)
192 .add("table", table)
193 .add("protocol", protocol)
194 .add("scope", scope)
195 .add("type", type)
196 .add("flags", flags)
197 .add("attributes", attributes)
198 .toString();
199 }
200
201 /**
202 * Decodes an rtnetlink message from an input buffer.
203 *
204 * @param buffer input buffer
205 * @param start starting position the rtnetlink message
206 * @param length length of the message
207 * @return rtnetlink message
208 * @throws DeserializationException if an rtnetlink message could not be
209 * decoded from the input buffer
210 */
211 public static RtNetlink decode(byte[] buffer, int start, int length)
212 throws DeserializationException {
213 checkInput(buffer, start, length, RT_NETLINK_LENGTH);
214
215 ByteBuffer bb = ByteBuffer.wrap(buffer, start, length);
216
217 short addressFamily = (short) (bb.get() & MASK);
218 int dstLength = bb.get() & MASK;
219 int srcLength = bb.get() & MASK;
220 short tos = (short) (bb.get() & MASK);
221 short table = (short) (bb.get() & MASK);
222 short protocol = (short) (bb.get() & MASK);
223 short scope = (short) (bb.get() & MASK);
224 short type = (short) (bb.get() & MASK);
225 long flags = Integer.reverseBytes(bb.getInt());
226 List<RouteAttribute> attributes = new ArrayList<>();
227
Jonathan Hart916bf892016-01-27 16:42:55 -0800228 RtProtocol rtProtocol = RtProtocol.get(protocol);
229
Jonathan Hart3930f632015-10-19 12:12:51 -0700230 while (bb.hasRemaining()) {
231 RouteAttribute attribute = RouteAttribute.decode(buffer, bb.position(),
232 bb.limit() - bb.position());
233 attributes.add(attribute);
234 bb.position(bb.position() + attribute.length());
235 }
236
237 return new RtNetlink(
238 addressFamily,
239 dstLength,
240 srcLength,
241 tos,
242 table,
Jonathan Hart916bf892016-01-27 16:42:55 -0800243 rtProtocol,
Jonathan Hart3930f632015-10-19 12:12:51 -0700244 scope,
245 type,
246 flags,
247 attributes);
248 }
249
Kalhee Kimba366062017-11-07 16:32:09 +0000250
251 /**
252 * Encode the RtNetlink contents into the ChannelBuffer.
253 *
254 * @param cb channelbuffer to be filled in
255 */
256 public void encode(ChannelBuffer cb) {
257
258 cb.writeByte(addressFamily);
259 cb.writeByte(dstLength);
260 cb.writeByte(srcLength);
261 cb.writeByte(tos);
262 cb.writeByte(table);
263 cb.writeByte(protocol.value());
264 cb.writeByte(scope);
265 cb.writeByte(type);
266 cb.writeInt(Integer.reverseBytes((int) flags));
267
268 for (RouteAttribute attribute : attributes()) {
269 attribute.encode(cb);
270 }
271 }
272
Kalhee Kim715dd732018-01-23 14:39:56 +0000273 /**
274 * Returns a new RtNetlink builder.
275 *
276 * @return RtNetlink builder
277 */
278 public static Builder builder() {
279 return new Builder();
280 }
281
282 /**
283 * RtNetlink Builder.
284 */
285 public static final class Builder {
286
287 private short addressFamily = RT_ADDRESS_FAMILY_INET;
288 private int dstLength = 0;
289 private int srcLength = 0;
290 private short tos = 0;
291 private short table = 0;
292 private RtProtocol protocol = RtProtocol.ZEBRA;
293 private short scope = 0;
294 private short type = FpmHeader.FPM_TYPE_NETLINK;
295 private long flags = 0;
296 private List<RouteAttribute> attributes = new ArrayList<>();
297
298 /**
299 * Hide class constructor.
300 */
301 private Builder() {
302 }
303
304 /**
305 * Sets addressFamily for the RtNetlink that will be built.
306 *
307 * @param addressFamily to use for built RtNetlink
308 * @return this builder
309 */
310 public Builder addressFamily(short addressFamily) {
311 this.addressFamily = addressFamily;
312 return this;
313 }
314
315 /**
316 * Sets dstLength for the RtNetlink that will be built.
317 *
318 * @param dstLength to use for built RtNetlink
319 * @return this builder
320 */
321 public Builder dstLength(int dstLength) {
322 this.dstLength = dstLength;
323 return this;
324 }
325
326 /**
327 * Sets srcLength for the RtNetlink that will be built.
328 *
329 * @param srcLength to use for built RtNetlink
330 * @return this builder
331 */
332 public Builder srcLength(int srcLength) {
333 this.srcLength = srcLength;
334 return this;
335 }
336
337 /**
338 * Sets tos for the RtNetlink that will be built.
339 *
340 * @param tos to use for built RtNetlink
341 * @return this builder
342 */
343 public Builder tos(short tos) {
344 this.tos = tos;
345 return this;
346 }
347
348 /**
349 * Sets table for the RtNetlink that will be built.
350 *
351 * @param table to use for built RtNetlink
352 * @return this builder
353 */
354 public Builder table(short table) {
355 this.table = table;
356 return this;
357 }
358
359 /**
360 * Sets protocol for the RtNetlink that will be built.
361 *
362 * @param protocol to use for built RtNetlink
363 * @return this builder
364 */
365 public Builder protocol(RtProtocol protocol) {
366 this.protocol = protocol;
367 return this;
368 }
369
370 /**
371 * Sets scope for the RtNetlink that will be built.
372 *
373 * @param scope to use for built RtNetlink
374 * @return this builder
375 */
376 public Builder scope(short scope) {
377 this.scope = scope;
378 return this;
379 }
380
381 /**
382 * Sets type for the RtNetlink that will be built.
383 *
384 * @param type to use for built RtNetlink
385 * @return this builder
386 */
387 public Builder type(short type) {
388 this.type = type;
389 return this;
390 }
391
392 /**
393 * Sets flags for the RtNetlink that will be built.
394 *
395 * @param flags to use for built RtNetlink
396 * @return this builder
397 */
398 public Builder flags(long flags) {
399 this.flags = flags;
400 return this;
401 }
402
403 /**
404 * Adds attribute for the RtNetlink that will be built.
405 *
406 * @param ra to add to list of route attributes
407 * @return this builder
408 */
409 public Builder routeAttribute(RouteAttribute ra) {
410 attributes.add(ra);
411 return this;
412 }
413
414 /**
415 * Builds the RtNetlink.
416 *
417 * @return RtNetlink reference
418 */
419 public RtNetlink build() {
420 return new RtNetlink(addressFamily,
421 dstLength,
422 srcLength,
423 tos,
424 table,
425 protocol,
426 scope,
427 type,
428 flags,
429 attributes);
430 }
431 }
Jonathan Hart3930f632015-10-19 12:12:51 -0700432}