blob: df84ed60a87e9f435f1e14f16fe2eb39df8983be [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 Kimba366062017-11-07 16:32:09 +000058 public 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
Jonathan Hart3930f632015-10-19 12:12:51 -0700191}