2 * Copyright 2015 Open Networking Laboratory
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org.onosproject.bgpio.protocol.ver4;
18 import java.util.LinkedList;
19 import java.util.List;
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;
34 import com.google.common.base.MoreObjects;
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
41 public class BgpUpdateMsgVer4 implements BgpUpdateMsg {
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 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
53 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
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 +-----------------------------------------------------+
69 protected static final Logger log = LoggerFactory
70 .getLogger(BgpUpdateMsgVer4.class);
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();
81 private List<IpPrefix> withdrawnRoutes;
82 private BgpPathAttributes bgpPathAttributes;
83 private BgpHeader bgpHeader;
84 private List<IpPrefix> nlri;
87 * Constructor to initialize parameters for BGP Update message.
89 * @param bgpHeader in Update message
90 * @param withdrawnRoutes withdrawn routes
91 * @param bgpPathAttributes BGP Path attributes
92 * @param nlri Network Layer Reachability Information
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;
103 * Reader reads BGP Update Message from the channel buffer.
105 static class Reader implements BgpMessageReader<BgpUpdateMsg> {
108 public BgpUpdateMsg readFrom(ChannelBuffer cb, BgpHeader bgpHeader)
109 throws BgpParseException {
111 if (cb.readableBytes() != (bgpHeader.getLength() - MINIMUM_COMMON_HEADER_LENGTH)) {
112 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
113 BgpErrorType.BAD_MESSAGE_LENGTH, bgpHeader.getLength());
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();
122 if (cb.readableBytes() < withDrwLen) {
123 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
124 BgpErrorType.MALFORMED_ATTRIBUTE_LIST,
127 ChannelBuffer tempCb = cb.readBytes(withDrwLen);
128 if (withDrwLen != 0) {
129 // Parsing WithdrawnRoutes
130 withDrwRoutes = parseWithdrawnRoutes(tempCb);
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);
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);
145 if (totPathAttrLen != 0) {
146 // Parsing BGPPathAttributes
147 if (cb.readableBytes() < totPathAttrLen) {
149 .validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
150 BgpErrorType.MALFORMED_ATTRIBUTE_LIST,
153 tempCb = cb.readBytes(totPathAttrLen);
154 bgpPathAttributes = BgpPathAttributes.read(tempCb);
156 if (cb.readableBytes() > 0) {
158 nlri = parseNlri(cb);
160 return new BgpUpdateMsgVer4(bgpHeader, withDrwRoutes,
161 bgpPathAttributes, nlri);
166 * Parses NLRI from channel buffer.
168 * @param cb channelBuffer
169 * @return list of IP Prefix
170 * @throws BgpParseException while parsing NLRI
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();
179 byte[] prefix = new byte[] {0};
180 ipPrefix = Validation.bytesToPrefix(prefix, length);
183 int len = length / BYTE_IN_BITS;
184 int reminder = length % BYTE_IN_BITS;
188 if (cb.readableBytes() < len) {
189 Validation.validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
190 BgpErrorType.MALFORMED_ATTRIBUTE_LIST,
193 byte[] prefix = new byte[len];
194 cb.readBytes(prefix, 0, len);
195 ipPrefix = Validation.bytesToPrefix(prefix, length);
203 * Parsing withdrawn routes from channel buffer.
205 * @param cb channelBuffer
206 * @return list of IP prefix
207 * @throws BgpParseException while parsing withdrawn routes
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();
216 byte[] prefix = new byte[] {0};
217 ipPrefix = Validation.bytesToPrefix(prefix, length);
218 withDrwRoutes.add(ipPrefix);
220 int len = length / BYTE_IN_BITS;
221 int reminder = length % BYTE_IN_BITS;
225 if (cb.readableBytes() < len) {
227 .validateLen(BgpErrorType.UPDATE_MESSAGE_ERROR,
228 BgpErrorType.MALFORMED_ATTRIBUTE_LIST,
231 byte[] prefix = new byte[len];
232 cb.readBytes(prefix, 0, len);
233 ipPrefix = Validation.bytesToPrefix(prefix, length);
234 withDrwRoutes.add(ipPrefix);
237 return withDrwRoutes;
241 public BgpVersion getVersion() {
242 return BgpVersion.BGP_4;
246 public BgpType getType() {
247 return BgpType.UPDATE;
251 public void writeTo(ChannelBuffer channelBuffer) throws BgpParseException {
252 //Not to be implemented as of now
256 public BgpPathAttributes bgpPathAttributes() {
257 return this.bgpPathAttributes;
261 public List<IpPrefix> withdrawnRoutes() {
262 return withdrawnRoutes;
266 public List<IpPrefix> nlri() {
271 public BgpHeader getHeader() {
272 return this.bgpHeader;
276 public String toString() {
277 return MoreObjects.toStringHelper(getClass())
279 .add("bgpHeader", bgpHeader)
280 .add("withDrawnRoutes", withdrawnRoutes)
282 .add("bgpPathAttributes", bgpPathAttributes)