blob: 4d6af5947a9ff74959d990dd842e8b8c97c13028 [file] [log] [blame]
Priyanka B425e3c52015-11-13 14:31:15 +05301/*
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 */
16package org.onosproject.bgpio.protocol.ver4;
17
18import java.util.LinkedList;
19import java.util.List;
20
21import org.jboss.netty.buffer.ChannelBuffer;
22import org.onlab.packet.IpPrefix;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053023import org.onosproject.bgpio.exceptions.BgpParseException;
24import org.onosproject.bgpio.protocol.BgpMessageReader;
25import org.onosproject.bgpio.protocol.BgpType;
Priyanka B425e3c52015-11-13 14:31:15 +053026import org.onosproject.bgpio.protocol.BgpUpdateMsg;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053027import org.onosproject.bgpio.types.BgpErrorType;
28import org.onosproject.bgpio.types.BgpHeader;
Priyanka B425e3c52015-11-13 14:31:15 +053029import org.onosproject.bgpio.util.Validation;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053030import org.onosproject.bgpio.protocol.BgpVersion;
Priyanka B425e3c52015-11-13 14:31:15 +053031import org.slf4j.Logger;
32import org.slf4j.LoggerFactory;
33
34import 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 */
41public 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;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053078 public static final BgpType MSG_TYPE = BgpType.UPDATE;
Priyanka B425e3c52015-11-13 14:31:15 +053079 public static final BgpUpdateMsgVer4.Reader READER = new Reader();
80
81 private List<IpPrefix> withdrawnRoutes;
82 private BgpPathAttributes bgpPathAttributes;
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053083 private BgpHeader bgpHeader;
Priyanka B425e3c52015-11-13 14:31:15 +053084 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 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +053094 public BgpUpdateMsgVer4(BgpHeader bgpHeader, List<IpPrefix> withdrawnRoutes,
Priyanka B425e3c52015-11-13 14:31:15 +053095 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 */
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530105 static class Reader implements BgpMessageReader<BgpUpdateMsg> {
Priyanka B425e3c52015-11-13 14:31:15 +0530106
107 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530108 public BgpUpdateMsg readFrom(ChannelBuffer cb, BgpHeader bgpHeader)
109 throws BgpParseException {
Priyanka B425e3c52015-11-13 14:31:15 +0530110
111 if (cb.readableBytes() != (bgpHeader.getLength() - MINIMUM_COMMON_HEADER_LENGTH)) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530112 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
113 BgpErrorType.BAD_MESSAGE_LENGTH, bgpHeader.getLength());
Priyanka B425e3c52015-11-13 14:31:15 +0530114 }
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) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530123 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
124 BgpErrorType.MALFORMED_ATTRIBUTE_LIST,
Priyanka B425e3c52015-11-13 14:31:15 +0530125 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");
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530134 throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR,
135 BgpErrorType.MALFORMED_ATTRIBUTE_LIST, null);
Priyanka B425e3c52015-11-13 14:31:15 +0530136 }
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()) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530142 throw new BgpParseException(BgpErrorType.UPDATE_MESSAGE_ERROR,
143 BgpErrorType.MALFORMED_ATTRIBUTE_LIST, null);
Priyanka B425e3c52015-11-13 14:31:15 +0530144 }
145 if (totPathAttrLen != 0) {
146 // Parsing BGPPathAttributes
147 if (cb.readableBytes() < totPathAttrLen) {
148 Validation
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530149 .validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
150 BgpErrorType.MALFORMED_ATTRIBUTE_LIST,
Priyanka B425e3c52015-11-13 14:31:15 +0530151 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
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530170 * @throws BgpParseException while parsing NLRI
Priyanka B425e3c52015-11-13 14:31:15 +0530171 */
172 public static LinkedList<IpPrefix> parseNlri(ChannelBuffer cb)
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530173 throws BgpParseException {
Priyanka B425e3c52015-11-13 14:31:15 +0530174 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) {
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530189 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
190 BgpErrorType.MALFORMED_ATTRIBUTE_LIST,
Priyanka B425e3c52015-11-13 14:31:15 +0530191 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
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530207 * @throws BgpParseException while parsing withdrawn routes
Priyanka B425e3c52015-11-13 14:31:15 +0530208 */
209 public static LinkedList<IpPrefix> parseWithdrawnRoutes(ChannelBuffer cb)
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530210 throws BgpParseException {
Priyanka B425e3c52015-11-13 14:31:15 +0530211 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
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530227 .validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
228 BgpErrorType.MALFORMED_ATTRIBUTE_LIST,
Priyanka B425e3c52015-11-13 14:31:15 +0530229 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
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530241 public BgpVersion getVersion() {
242 return BgpVersion.BGP_4;
Priyanka B425e3c52015-11-13 14:31:15 +0530243 }
244
245 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530246 public BgpType getType() {
247 return BgpType.UPDATE;
Priyanka B425e3c52015-11-13 14:31:15 +0530248 }
249
250 @Override
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530251 public void writeTo(ChannelBuffer channelBuffer) throws BgpParseException {
Priyanka B425e3c52015-11-13 14:31:15 +0530252 //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
Shashikanth VH5dd8dbe2015-11-26 13:22:18 +0530271 public BgpHeader getHeader() {
Priyanka B425e3c52015-11-13 14:31:15 +0530272 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}