Priyanka B
Committed by Gerrit Code Review

[Emu] [ONOS-2599] Implement BGP Notification protocol Messgae parsing, Decode and encoding

Change-Id: I93c2e0787a4f16810a9fec655b33ebef73e001e0
1 +/*
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 + */
16 +package org.onosproject.bgpio.protocol;
17 +
18 +import org.onosproject.bgpio.exceptions.BGPParseException;
19 +import org.onosproject.bgpio.types.BGPHeader;
20 +
21 +/**
22 + * Abstraction of an entity providing BGP Notification Message.
23 + */
24 +public interface BGPNotificationMsg extends BGPMessage {
25 + /**
26 + * Returns errorCode in Notification message.
27 + *
28 + * @return errorCode in Notification message
29 + */
30 + byte getErrorCode();
31 +
32 + /**
33 + * Returns error SubCode in Notification message.
34 + *
35 + * @return error SubCode in Notification message
36 + */
37 + byte getErrorSubCode();
38 +
39 + /**
40 + * Returns error data in Notification message.
41 + *
42 + * @return error data in Notification message
43 + */
44 + byte[] getData();
45 +
46 + /**
47 + * Builder interface with get and set functions to build Notification
48 + * message.
49 + */
50 + public interface Builder extends BGPMessage.Builder {
51 +
52 + @Override
53 + BGPNotificationMsg build() throws BGPParseException;
54 +
55 + /**
56 + * Sets notification message header and returns its builder.
57 + *
58 + * @param header of notification message
59 + * @return Builder by setting notification message header
60 + */
61 + Builder setNotificationMsgHeader(BGPHeader header);
62 +
63 + /**
64 + * Sets errorCode in notification message and return its builder.
65 + *
66 + * @param errorCode in notification message
67 + * @return builder by setting ErrorCode in notification message
68 + */
69 + Builder setErrorCode(byte errorCode);
70 +
71 + /**
72 + * Sets error SubCode in notification message and return its builder.
73 + *
74 + * @param errorSubCode in notification Message
75 + * @return builder by setting ErrorSubCode in notification Message
76 + */
77 + Builder setErrorSubCode(byte errorSubCode);
78 +
79 + /**
80 + * Sets error data in notification message and return its builder.
81 + *
82 + * @param data in notification message
83 + * @return builder by setting Data in notification message
84 + */
85 + Builder setData(byte[] data);
86 + }
87 +}
...\ No newline at end of file ...\ No newline at end of file
1 +/*
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 + */
16 +package org.onosproject.bgpio.protocol.ver4;
17 +
18 +import org.jboss.netty.buffer.ChannelBuffer;
19 +import org.onosproject.bgpio.exceptions.BGPParseException;
20 +import org.onosproject.bgpio.protocol.BGPMessageReader;
21 +import org.onosproject.bgpio.protocol.BGPMessageWriter;
22 +import org.onosproject.bgpio.protocol.BGPNotificationMsg;
23 +import org.onosproject.bgpio.protocol.BGPType;
24 +import org.onosproject.bgpio.protocol.BGPVersion;
25 +import org.onosproject.bgpio.types.BGPErrorType;
26 +import org.onosproject.bgpio.types.BGPHeader;
27 +import org.slf4j.Logger;
28 +import org.slf4j.LoggerFactory;
29 +
30 +import com.google.common.base.MoreObjects;
31 +
32 +/**
33 + * A NOTIFICATION message is sent when an error condition is detected. The BGP connection is closed immediately after it
34 + * is sent.
35 + */
36 +class BGPNotificationMsgVer4 implements BGPNotificationMsg {
37 +
38 + /*
39 + 0 1 2 3
40 + 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
41 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42 + | Error code | Error subcode | Data (variable) |
43 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44 + REFERENCE : RFC 4271
45 + */
46 +
47 + protected static final Logger log = LoggerFactory.getLogger(BGPNotificationMsgVer4.class);
48 +
49 + static final byte PACKET_VERSION = 4;
50 + //BGPHeader(19) + Error code(1) + Error subcode(1)
51 + static final int TOTAL_MESSAGE_MIN_LENGTH = 21;
52 + static final int PACKET_MINIMUM_LENGTH = 2;
53 + static final BGPType MSG_TYPE = BGPType.NOTIFICATION;
54 + static final byte DEFAULT_ERRORSUBCODE = 0;
55 + static final byte[] MARKER = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
56 + 0x01, 0x01};
57 + static final byte MESSAGE_TYPE = 3;
58 + static final BGPHeader DEFAULT_MESSAGE_HEADER = new BGPHeader(MARKER, BGPHeader.DEFAULT_HEADER_LENGTH,
59 + MESSAGE_TYPE);
60 +
61 + private byte errorCode;
62 + private byte errorSubCode;
63 + private byte[] data;
64 + private BGPHeader bgpHeader;
65 + public static final BGPNotificationMsgVer4.Reader READER = new Reader();
66 +
67 + /**
68 + * Resets fields.
69 + */
70 + public BGPNotificationMsgVer4() {
71 + this.bgpHeader = null;
72 + this.data = null;
73 + this.errorCode = 0;
74 + this.errorSubCode = 0;
75 + }
76 +
77 + /**
78 + * Constructor to initialize parameters.
79 + *
80 + * @param bgpHeader BGP Header in notification message
81 + * @param errorCode error code
82 + * @param errorSubCode error subcode
83 + * @param data field
84 + */
85 + public BGPNotificationMsgVer4(BGPHeader bgpHeader, byte errorCode, byte errorSubCode, byte[] data) {
86 + this.bgpHeader = bgpHeader;
87 + this.data = data;
88 + this.errorCode = errorCode;
89 + this.errorSubCode = errorSubCode;
90 + }
91 +
92 + /**
93 + * Reader reads BGP Notification Message from the channel buffer.
94 + */
95 + static class Reader implements BGPMessageReader<BGPNotificationMsg> {
96 + @Override
97 + public BGPNotificationMsg readFrom(ChannelBuffer cb, BGPHeader bgpHeader) throws BGPParseException {
98 + byte errorCode;
99 + byte errorSubCode;
100 + if (cb.readableBytes() < PACKET_MINIMUM_LENGTH) {
101 + throw new BGPParseException("Not enough readable bytes");
102 + }
103 + errorCode = cb.readByte();
104 + errorSubCode = cb.readByte();
105 + //Message Length = 21 + Data Length
106 + int dataLength = bgpHeader.getLength() - TOTAL_MESSAGE_MIN_LENGTH;
107 + byte[] data = new byte[dataLength];
108 + cb.readBytes(data, 0, dataLength);
109 + return new BGPNotificationMsgVer4(bgpHeader, errorCode, errorSubCode, data);
110 + }
111 + }
112 +
113 + /**
114 + * Builder class for BGP notification message.
115 + */
116 + static class Builder implements BGPNotificationMsg.Builder {
117 + private byte errorCode;
118 + private byte errorSubCode;
119 + private byte[] data;
120 + private BGPHeader bgpHeader;
121 + private boolean isErrorCodeSet = false;
122 + private boolean isErrorSubCodeSet = false;
123 + private boolean isBGPHeaderSet = false;
124 +
125 + @Override
126 + public BGPVersion getVersion() {
127 + return BGPVersion.BGP_4;
128 + }
129 +
130 + @Override
131 + public BGPType getType() {
132 + return BGPType.NOTIFICATION;
133 + }
134 +
135 + @Override
136 + public BGPNotificationMsg build() throws BGPParseException {
137 + BGPHeader bgpHeader = this.isBGPHeaderSet ? this.bgpHeader : DEFAULT_MESSAGE_HEADER;
138 + if (!this.isErrorCodeSet) {
139 + throw new BGPParseException("Error code must be present");
140 + }
141 +
142 + byte errorSubCode = this.isErrorSubCodeSet ? this.errorSubCode : DEFAULT_ERRORSUBCODE;
143 + return new BGPNotificationMsgVer4(bgpHeader, this.errorCode, errorSubCode, this.data);
144 + }
145 +
146 + @Override
147 + public Builder setErrorCode(byte errorCode) {
148 + this.errorCode = errorCode;
149 + this.isErrorCodeSet = true;
150 + return this;
151 + }
152 +
153 + @Override
154 + public Builder setErrorSubCode(byte errorSubCode) {
155 + this.errorSubCode = errorSubCode;
156 + this.isErrorSubCodeSet = true;
157 + return this;
158 + }
159 +
160 + @Override
161 + public Builder setData(byte[] data) {
162 + this.data = data;
163 + return this;
164 + }
165 +
166 + @Override
167 + public Builder setNotificationMsgHeader(BGPHeader header) {
168 + this.bgpHeader = header;
169 + this.isBGPHeaderSet = true;
170 + return this;
171 + }
172 +
173 + @Override
174 + public BGPHeader getHeader() {
175 + return this.bgpHeader;
176 + }
177 +
178 + @Override
179 + public Builder setHeader(BGPHeader bgpMsgHeader) {
180 + this.bgpHeader = bgpMsgHeader;
181 + return this;
182 + }
183 + }
184 +
185 + @Override
186 + public BGPVersion getVersion() {
187 + return BGPVersion.BGP_4;
188 + }
189 +
190 + @Override
191 + public BGPType getType() {
192 + return BGPType.NOTIFICATION;
193 + }
194 +
195 + @Override
196 + public void writeTo(ChannelBuffer cb) throws BGPParseException {
197 + WRITER.write(cb, this);
198 + }
199 +
200 + static final Writer WRITER = new Writer();
201 +
202 + /**
203 + * Writer writes BGP notification message to channel buffer.
204 + */
205 + static class Writer implements BGPMessageWriter<BGPNotificationMsgVer4> {
206 + @Override
207 + public void write(ChannelBuffer cb, BGPNotificationMsgVer4 message) throws BGPParseException {
208 + int msgStartIndex = cb.writerIndex();
209 + int headerLenIndex = message.bgpHeader.write(cb);
210 + if (headerLenIndex <= 0) {
211 + throw new BGPParseException(BGPErrorType.MESSAGE_HEADER_ERROR, (byte) 0, null);
212 + }
213 + cb.writeByte(message.errorCode);
214 + cb.writeByte(message.errorSubCode);
215 + cb.writeBytes(message.data);
216 +
217 + //Update message length field in notification message
218 + int length = cb.writerIndex() - msgStartIndex;
219 + cb.setShort(headerLenIndex, (short) length);
220 + message.bgpHeader.setLength((short) length);
221 + }
222 + }
223 +
224 + @Override
225 + public byte getErrorCode() {
226 + return this.errorCode;
227 + }
228 +
229 + /**
230 + * Sets errorcode with specified errorcode.
231 + *
232 + * @param errorCode field
233 + */
234 + public void setErrorCode(byte errorCode) {
235 + this.errorCode = errorCode;
236 + }
237 +
238 + @Override
239 + public byte getErrorSubCode() {
240 + return this.errorSubCode;
241 + }
242 +
243 + /**
244 + * Sets error subcode with specified errorSubCode.
245 + *
246 + * @param errorSubCode field
247 + */
248 + public void setErrorSubCode(byte errorSubCode) {
249 + this.errorSubCode = errorSubCode;
250 + }
251 +
252 + @Override
253 + public byte[] getData() {
254 + return this.data;
255 + }
256 +
257 + /**
258 + * Sets error data with specified data.
259 + *
260 + * @param data field
261 + */
262 + public void setData(byte[] data) {
263 + this.data = data;
264 + }
265 +
266 + @Override
267 + public BGPHeader getHeader() {
268 + return this.bgpHeader;
269 + }
270 +
271 + @Override
272 + public String toString() {
273 + return MoreObjects.toStringHelper(getClass())
274 + .omitNullValues()
275 + .add("bgpHeader", bgpHeader)
276 + .add("data", data)
277 + .add("errorCode", errorCode)
278 + .add("errorSubCode", errorSubCode)
279 + .toString();
280 + }
281 +}
...\ No newline at end of file ...\ No newline at end of file