2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.protocol.bgp.parser.impl.message;
10 import java.util.Arrays;
12 import org.slf4j.Logger;
13 import org.slf4j.LoggerFactory;
15 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
16 import org.opendaylight.protocol.bgp.parser.BGPError;
17 import org.opendaylight.protocol.bgp.parser.message.BGPNotificationMessage;
18 import org.opendaylight.protocol.util.ByteArray;
19 import com.google.common.primitives.UnsignedBytes;
22 * Parser for BGPNotification message.
24 public final class BGPNotificationMessageParser {
26 private static final Logger logger = LoggerFactory.getLogger(BGPNotificationMessageParser.class);
28 private static final int ERROR_SIZE = 2; // bytes
30 private static class BGPErr {
31 private final int errorCode;
32 private final int errorSubcode;
34 public BGPErr(final int errorCode, final int errorSubcode) {
35 this.errorCode = errorCode;
36 this.errorSubcode = errorSubcode;
39 public int getErrorCode() {
40 return this.errorCode;
43 public int getErrorSubcode() {
44 return this.errorSubcode;
49 * Serializes BGP Notification message.
51 * @param msg to be serialized
52 * @return BGP Notification message converted to byte array
54 public static byte[] put(final BGPNotificationMessage msg) {
56 throw new IllegalArgumentException("BGP Notification message cannot be null");
57 logger.trace("Started serializing Notification message: {}", msg);
59 final byte[] msgBody = (msg.getData() == null) ? new byte[ERROR_SIZE] : new byte[ERROR_SIZE + msg.getData().length];
61 final BGPErr numError = parseBGPError(msg.getError());
64 throw new IllegalArgumentException("Cannot parse BGP Error: " + msg.getError());
66 msgBody[0] = ByteArray.intToBytes(numError.getErrorCode())[Integer.SIZE / Byte.SIZE - 1];
68 msgBody[1] = ByteArray.intToBytes(numError.getErrorSubcode())[Integer.SIZE / Byte.SIZE - 1];
70 if (msg.getData() != null)
71 System.arraycopy(msg.getData(), 0, msgBody, ERROR_SIZE, msg.getData().length);
72 logger.trace("Notification message serialized to: {}", Arrays.toString(msgBody));
77 * Parses BGP Notification message to bytes.
79 * @param bytes byte array to be parsed
80 * @return BGPNotification message
81 * @throws BGPDocumentedException
83 public static BGPNotificationMessage parse(final byte[] bytes) throws BGPDocumentedException {
84 if (bytes == null || bytes.length == 0)
85 throw new IllegalArgumentException("Byte array cannot be null or empty.");
86 logger.trace("Started parsing of notification message: {}", Arrays.toString(bytes));
88 if (bytes.length < ERROR_SIZE)
89 throw new BGPDocumentedException("Notification message too small.", BGPError.BAD_MSG_LENGTH, ByteArray.intToBytes(bytes.length));
90 final int errorCode = UnsignedBytes.toInt(bytes[0]);
91 final int errorSubcode = UnsignedBytes.toInt(bytes[1]);
93 final BGPError err = putBGPError(new BGPErr(errorCode, errorSubcode));
95 if (bytes.length > ERROR_SIZE) {
96 data = ByteArray.subByte(bytes, ERROR_SIZE, bytes.length - ERROR_SIZE);
98 logger.trace("Notification message was parsed: err = {}, data = {}.", err, Arrays.toString(data));
99 return (data == null) ? new BGPNotificationMessage(err) : new BGPNotificationMessage(err, data);
102 private static BGPErr parseBGPError(final BGPError err) {
104 case CONNECTION_NOT_SYNC:
105 return new BGPErr(1, 1);
107 return new BGPErr(1, 2);
109 return new BGPErr(1, 3);
110 case UNSPECIFIC_OPEN_ERROR:
111 return new BGPErr(2, 0);
112 case VERSION_NOT_SUPPORTED:
113 return new BGPErr(2, 1);
115 return new BGPErr(2, 2);
117 return new BGPErr(2, 3);
118 case OPT_PARAM_NOT_SUPPORTED:
119 return new BGPErr(2, 4);
120 case HOLD_TIME_NOT_ACC:
121 return new BGPErr(2, 6);
122 case MALFORMED_ATTR_LIST:
123 return new BGPErr(3, 1);
124 case WELL_KNOWN_ATTR_NOT_RECOGNIZED:
125 return new BGPErr(3, 2);
126 case WELL_KNOWN_ATTR_MISSING:
127 return new BGPErr(3, 3);
128 case ATTR_FLAGS_MISSING:
129 return new BGPErr(3, 4);
130 case ATTR_LENGTH_ERROR:
131 return new BGPErr(3, 5);
132 case ORIGIN_ATTR_NOT_VALID:
133 return new BGPErr(3, 6);
134 case NEXT_HOP_NOT_VALID:
135 return new BGPErr(3, 8);
137 return new BGPErr(3, 9);
138 case NETWORK_NOT_VALID:
139 return new BGPErr(3, 10);
140 case AS_PATH_MALFORMED:
141 return new BGPErr(3, 11);
142 case HOLD_TIMER_EXPIRED:
143 return new BGPErr(4, 0);
145 return new BGPErr(5, 0);
147 return new BGPErr(6, 0);
153 private static BGPError putBGPError(final BGPErr err) {
154 final int e = err.getErrorCode();
155 final int s = err.getErrorSubcode();
158 return BGPError.CONNECTION_NOT_SYNC;
160 return BGPError.BAD_MSG_LENGTH;
162 return BGPError.BAD_MSG_TYPE;
165 return BGPError.UNSPECIFIC_OPEN_ERROR;
167 return BGPError.VERSION_NOT_SUPPORTED;
169 return BGPError.BAD_PEER_AS;
171 return BGPError.BAD_BGP_ID;
173 return BGPError.OPT_PARAM_NOT_SUPPORTED;
175 return BGPError.HOLD_TIME_NOT_ACC;
178 return BGPError.MALFORMED_ATTR_LIST;
180 return BGPError.WELL_KNOWN_ATTR_NOT_RECOGNIZED;
182 return BGPError.WELL_KNOWN_ATTR_MISSING;
184 return BGPError.ATTR_FLAGS_MISSING;
186 return BGPError.ATTR_LENGTH_ERROR;
188 return BGPError.ORIGIN_ATTR_NOT_VALID;
190 return BGPError.NEXT_HOP_NOT_VALID;
192 return BGPError.OPT_ATTR_ERROR;
194 return BGPError.NETWORK_NOT_VALID;
196 return BGPError.AS_PATH_MALFORMED;
198 return BGPError.HOLD_TIMER_EXPIRED;
200 return BGPError.FSM_ERROR;
202 return BGPError.CEASE;
203 throw new IllegalArgumentException("BGP Error code " + e + " and subcode " + s + " not recognized.");