Priyanka B
Committed by Gerrit Code Review

[Emu] [ONOS-2600] Implement Basic BGP Update protocol message parsing and decode…

… excluding path attributes.

Change-Id: I37ed38cb79583fbbb31057dafc06df245aef3c49
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 +
17 +package org.onosproject.bgpio.protocol;
18 +
19 +import java.util.List;
20 +
21 +import org.onlab.packet.IpPrefix;
22 +import org.onosproject.bgpio.protocol.ver4.BgpPathAttributes;
23 +
24 +/**
25 + * Abstraction of an entity providing BGP Update Message.
26 + */
27 +public interface BgpUpdateMsg extends BGPMessage {
28 + /**
29 + * Returns path attributes in BGP Update Message.
30 + *
31 + * @return path attributes in BGP Update Message
32 + */
33 + BgpPathAttributes bgpPathAttributes();
34 +
35 + /**
36 + * Returns withdrawn Routes.
37 + *
38 + * @return withdrawn Routes
39 + */
40 + List<IpPrefix> withdrawnRoutes();
41 +
42 + /**
43 + * Returns NLRI list of prefix.
44 + *
45 + * @return NLRI list of prefix
46 + */
47 + List<IpPrefix> nlri();
48 +}
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 java.util.LinkedList;
19 +import java.util.List;
20 +
21 +import org.jboss.netty.buffer.ChannelBuffer;
22 +import org.onlab.packet.IpPrefix;
23 +import org.onosproject.bgpio.exceptions.BGPParseException;
24 +import org.onosproject.bgpio.protocol.BGPMessageReader;
25 +import org.onosproject.bgpio.protocol.BGPType;
26 +import org.onosproject.bgpio.protocol.BgpUpdateMsg;
27 +import org.onosproject.bgpio.types.BGPErrorType;
28 +import org.onosproject.bgpio.types.BGPHeader;
29 +import org.onosproject.bgpio.util.Validation;
30 +import org.onosproject.bgpio.protocol.BGPVersion;
31 +import org.slf4j.Logger;
32 +import org.slf4j.LoggerFactory;
33 +
34 +import com.google.common.base.MoreObjects;
35 +
36 +/**
37 + * BGP Update Message: UPDATE messages are used to transfer routing information
38 + * between BGP peers. The information in the UPDATE message is used by core to
39 + * construct a graph
40 + */
41 +public class BgpUpdateMsgVer4 implements BgpUpdateMsg {
42 +
43 + /* 0 1 2 3
44 + 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
45 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46 + | |
47 + + +
48 + | |
49 + + +
50 + | Marker |
51 + + +
52 + | |
53 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54 + | Length | Type |
55 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56 + | Withdrawn Routes Length (2 octets) |
57 + +-----------------------------------------------------+
58 + | Withdrawn Routes (variable) |
59 + +-----------------------------------------------------+
60 + | Total Path Attribute Length (2 octets) |
61 + +-----------------------------------------------------+
62 + | Path Attributes (variable) |
63 + +-----------------------------------------------------+
64 + | Network Layer Reachability Information (variable) |
65 + +-----------------------------------------------------+
66 + REFERENCE : RFC 4271
67 + */
68 +
69 + protected static final Logger log = LoggerFactory
70 + .getLogger(BgpUpdateMsgVer4.class);
71 +
72 + public static final byte PACKET_VERSION = 4;
73 + //Withdrawn Routes Length(2) + Total Path Attribute Length(2)
74 + public static final int PACKET_MINIMUM_LENGTH = 4;
75 + public static final int BYTE_IN_BITS = 8;
76 + public static final int MIN_LEN_AFTER_WITHDRW_ROUTES = 2;
77 + public static final int MINIMUM_COMMON_HEADER_LENGTH = 19;
78 + public static final BGPType MSG_TYPE = BGPType.UPDATE;
79 + public static final BgpUpdateMsgVer4.Reader READER = new Reader();
80 +
81 + private List<IpPrefix> withdrawnRoutes;
82 + private BgpPathAttributes bgpPathAttributes;
83 + private BGPHeader bgpHeader;
84 + private List<IpPrefix> nlri;
85 +
86 + /**
87 + * Constructor to initialize parameters for BGP Update message.
88 + *
89 + * @param bgpHeader in Update message
90 + * @param withdrawnRoutes withdrawn routes
91 + * @param bgpPathAttributes BGP Path attributes
92 + * @param nlri Network Layer Reachability Information
93 + */
94 + public BgpUpdateMsgVer4(BGPHeader bgpHeader, List<IpPrefix> withdrawnRoutes,
95 + BgpPathAttributes bgpPathAttributes, List<IpPrefix> nlri) {
96 + this.bgpHeader = bgpHeader;
97 + this.withdrawnRoutes = withdrawnRoutes;
98 + this.bgpPathAttributes = bgpPathAttributes;
99 + this.nlri = nlri;
100 + }
101 +
102 + /**
103 + * Reader reads BGP Update Message from the channel buffer.
104 + */
105 + static class Reader implements BGPMessageReader<BgpUpdateMsg> {
106 +
107 + @Override
108 + public BgpUpdateMsg readFrom(ChannelBuffer cb, BGPHeader bgpHeader)
109 + throws BGPParseException {
110 +
111 + if (cb.readableBytes() != (bgpHeader.getLength() - MINIMUM_COMMON_HEADER_LENGTH)) {
112 + Validation.validateLen(BGPErrorType.UPDATE_MESSAGE_ERROR,
113 + BGPErrorType.BAD_MESSAGE_LENGTH, bgpHeader.getLength());
114 + }
115 +
116 + LinkedList<IpPrefix> withDrwRoutes = new LinkedList<>();
117 + LinkedList<IpPrefix> nlri = new LinkedList<>();
118 + BgpPathAttributes bgpPathAttributes = new BgpPathAttributes();
119 + // Reading Withdrawn Routes Length
120 + Short withDrwLen = cb.readShort();
121 +
122 + if (cb.readableBytes() < withDrwLen) {
123 + Validation.validateLen(BGPErrorType.UPDATE_MESSAGE_ERROR,
124 + BGPErrorType.MALFORMED_ATTRIBUTE_LIST,
125 + cb.readableBytes());
126 + }
127 + ChannelBuffer tempCb = cb.readBytes(withDrwLen);
128 + if (withDrwLen != 0) {
129 + // Parsing WithdrawnRoutes
130 + withDrwRoutes = parseWithdrawnRoutes(tempCb);
131 + }
132 + if (cb.readableBytes() < MIN_LEN_AFTER_WITHDRW_ROUTES) {
133 + log.debug("Bgp Path Attribute len field not present");
134 + throw new BGPParseException(BGPErrorType.UPDATE_MESSAGE_ERROR,
135 + BGPErrorType.MALFORMED_ATTRIBUTE_LIST, null);
136 + }
137 +
138 + // Reading Total Path Attribute Length
139 + short totPathAttrLen = cb.readShort();
140 + int len = withDrwLen + totPathAttrLen + PACKET_MINIMUM_LENGTH;
141 + if (len > bgpHeader.getLength()) {
142 + throw new BGPParseException(BGPErrorType.UPDATE_MESSAGE_ERROR,
143 + BGPErrorType.MALFORMED_ATTRIBUTE_LIST, null);
144 + }
145 + if (totPathAttrLen != 0) {
146 + // Parsing BGPPathAttributes
147 + if (cb.readableBytes() < totPathAttrLen) {
148 + Validation
149 + .validateLen(BGPErrorType.UPDATE_MESSAGE_ERROR,
150 + BGPErrorType.MALFORMED_ATTRIBUTE_LIST,
151 + cb.readableBytes());
152 + }
153 + tempCb = cb.readBytes(totPathAttrLen);
154 + bgpPathAttributes = BgpPathAttributes.read(tempCb);
155 + }
156 + if (cb.readableBytes() > 0) {
157 + // Parsing NLRI
158 + nlri = parseNlri(cb);
159 + }
160 + return new BgpUpdateMsgVer4(bgpHeader, withDrwRoutes,
161 + bgpPathAttributes, nlri);
162 + }
163 + }
164 +
165 + /**
166 + * Parses NLRI from channel buffer.
167 + *
168 + * @param cb channelBuffer
169 + * @return list of IP Prefix
170 + * @throws BGPParseException while parsing NLRI
171 + */
172 + public static LinkedList<IpPrefix> parseNlri(ChannelBuffer cb)
173 + throws BGPParseException {
174 + LinkedList<IpPrefix> nlri = new LinkedList<>();
175 + while (cb.readableBytes() > 0) {
176 + int length = cb.readByte();
177 + IpPrefix ipPrefix;
178 + if (length == 0) {
179 + byte[] prefix = new byte[] {0};
180 + ipPrefix = Validation.bytesToPrefix(prefix, length);
181 + nlri.add(ipPrefix);
182 + } else {
183 + int len = length / BYTE_IN_BITS;
184 + int reminder = length % BYTE_IN_BITS;
185 + if (reminder > 0) {
186 + len = len + 1;
187 + }
188 + if (cb.readableBytes() < len) {
189 + Validation.validateLen(BGPErrorType.UPDATE_MESSAGE_ERROR,
190 + BGPErrorType.MALFORMED_ATTRIBUTE_LIST,
191 + cb.readableBytes());
192 + }
193 + byte[] prefix = new byte[len];
194 + cb.readBytes(prefix, 0, len);
195 + ipPrefix = Validation.bytesToPrefix(prefix, length);
196 + nlri.add(ipPrefix);
197 + }
198 + }
199 + return nlri;
200 + }
201 +
202 + /**
203 + * Parsing withdrawn routes from channel buffer.
204 + *
205 + * @param cb channelBuffer
206 + * @return list of IP prefix
207 + * @throws BGPParseException while parsing withdrawn routes
208 + */
209 + public static LinkedList<IpPrefix> parseWithdrawnRoutes(ChannelBuffer cb)
210 + throws BGPParseException {
211 + LinkedList<IpPrefix> withDrwRoutes = new LinkedList<>();
212 + while (cb.readableBytes() > 0) {
213 + int length = cb.readByte();
214 + IpPrefix ipPrefix;
215 + if (length == 0) {
216 + byte[] prefix = new byte[] {0};
217 + ipPrefix = Validation.bytesToPrefix(prefix, length);
218 + withDrwRoutes.add(ipPrefix);
219 + } else {
220 + int len = length / BYTE_IN_BITS;
221 + int reminder = length % BYTE_IN_BITS;
222 + if (reminder > 0) {
223 + len = len + 1;
224 + }
225 + if (cb.readableBytes() < len) {
226 + Validation
227 + .validateLen(BGPErrorType.UPDATE_MESSAGE_ERROR,
228 + BGPErrorType.MALFORMED_ATTRIBUTE_LIST,
229 + cb.readableBytes());
230 + }
231 + byte[] prefix = new byte[len];
232 + cb.readBytes(prefix, 0, len);
233 + ipPrefix = Validation.bytesToPrefix(prefix, length);
234 + withDrwRoutes.add(ipPrefix);
235 + }
236 + }
237 + return withDrwRoutes;
238 + }
239 +
240 + @Override
241 + public BGPVersion getVersion() {
242 + return BGPVersion.BGP_4;
243 + }
244 +
245 + @Override
246 + public BGPType getType() {
247 + return BGPType.UPDATE;
248 + }
249 +
250 + @Override
251 + public void writeTo(ChannelBuffer channelBuffer) throws BGPParseException {
252 + //Not to be implemented as of now
253 + }
254 +
255 + @Override
256 + public BgpPathAttributes bgpPathAttributes() {
257 + return this.bgpPathAttributes;
258 + }
259 +
260 + @Override
261 + public List<IpPrefix> withdrawnRoutes() {
262 + return withdrawnRoutes;
263 + }
264 +
265 + @Override
266 + public List<IpPrefix> nlri() {
267 + return nlri;
268 + }
269 +
270 + @Override
271 + public BGPHeader getHeader() {
272 + return this.bgpHeader;
273 + }
274 +
275 + @Override
276 + public String toString() {
277 + return MoreObjects.toStringHelper(getClass())
278 + .omitNullValues()
279 + .add("bgpHeader", bgpHeader)
280 + .add("withDrawnRoutes", withdrawnRoutes)
281 + .add("nlri", nlri)
282 + .add("bgpPathAttributes", bgpPathAttributes)
283 + .toString();
284 + }
285 +}