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.open;
10 import java.util.Arrays;
11 import java.util.Map.Entry;
13 import org.slf4j.Logger;
14 import org.slf4j.LoggerFactory;
17 import org.opendaylight.protocol.bgp.concepts.BGPAddressFamily;
18 import org.opendaylight.protocol.bgp.concepts.BGPSubsequentAddressFamily;
19 import org.opendaylight.protocol.bgp.concepts.BGPTableType;
20 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
21 import org.opendaylight.protocol.bgp.parser.impl.message.update.MPReachParser;
22 import org.opendaylight.protocol.bgp.parser.parameter.AS4BytesCapability;
23 import org.opendaylight.protocol.bgp.parser.parameter.CapabilityParameter;
24 import org.opendaylight.protocol.bgp.parser.parameter.GracefulCapability;
25 import org.opendaylight.protocol.bgp.parser.parameter.MultiprotocolCapability;
26 import org.opendaylight.protocol.util.ByteArray;
27 import org.opendaylight.protocol.concepts.ASNumber;
28 import com.google.common.primitives.UnsignedBytes;
31 * Parser for BGP Capability Parameter.
33 public final class CapabilityParameterParser {
35 private static final Logger logger = LoggerFactory.getLogger(CapabilityParameterParser.class);
37 private static final int CODE_SIZE = 1; // bytes
38 private static final int LENGTH_SIZE = 1; // bytes
39 private static final int AFI_SIZE = 2; // bytes
40 private static final int SAFI_SIZE = 1; // bytes
42 private CapabilityParameterParser() {
47 * Serializes given BGP Capability Parameter to byte array.
49 * @param param BGP Capability to be serialized
50 * @return BGP Capability converted to byte array
52 public static byte[] put(final CapabilityParameter cap) {
54 throw new IllegalArgumentException("BGP Capability cannot be null");
55 logger.trace("Started serializing BGP Capability: {}", cap);
57 if (cap instanceof MultiprotocolCapability) {
58 value = putMultiProtocolParameterValue((MultiprotocolCapability) cap);
59 } else if (cap instanceof GracefulCapability) {
60 value = putGracefulParameterValue((GracefulCapability) cap);
61 } else if (cap instanceof AS4BytesCapability) {
62 value = putAS4BytesParameterValue((AS4BytesCapability) cap);
64 final byte[] bytes = new byte[CODE_SIZE + LENGTH_SIZE + value.length];
65 bytes[0] = ByteArray.intToBytes(cap.getCode())[Integer.SIZE / Byte.SIZE - 1];
66 bytes[1] = ByteArray.intToBytes(value.length)[Integer.SIZE / Byte.SIZE - 1];
67 System.arraycopy(value, 0, bytes, CODE_SIZE + LENGTH_SIZE, value.length);
68 logger.trace("BGP Parameter serialized to: {}", Arrays.toString(bytes));
73 * Parses given byte array to Capability Parameter. Only Multiprotocol capability is supported.
75 * @param bytes byte array representing BGP Parameters
76 * @return list of BGP Parameters
77 * @throws BGPParsingException if the parsing was unsuccessful
79 public static CapabilityParameter parse(final byte[] bytes) throws BGPParsingException {
80 if (bytes == null || bytes.length == 0)
81 throw new IllegalArgumentException("Byte array cannot be null or empty.");
82 logger.trace("Started parsing of BGP Capability: {}", Arrays.toString(bytes));
84 final int capCode = UnsignedBytes.toInt(bytes[byteOffset++]);
85 final int capLength = UnsignedBytes.toInt(bytes[byteOffset++]);
86 if (capCode == MultiprotocolCapability.CODE) {
87 logger.trace("Parsed BGP Capability.");
88 return parseMultiProtocolParameterValue(ByteArray.subByte(bytes, byteOffset, capLength));
89 } else if (capCode == AS4BytesCapability.CODE) {
90 logger.trace("Parsed AS4B Capability.");
91 return parseAS4BParameterValue(ByteArray.subByte(bytes, byteOffset, capLength));
93 logger.debug("Only Multiprotocol Capability Parameter is supported. Received code {}", capCode);
97 private static byte[] putGracefulParameterValue(final GracefulCapability param) {
98 final int RESTART_FLAGS_SIZE = 4; // bits
99 final int TIMER_SIZE = 12; // bits
100 final int AFI_SIZE = 2; // bytes
101 final int SAFI_SIZE = 1; // bytes
102 final int AF_FLAGS_SIZE = 1; // bytes
103 final byte[] bytes = new byte[(RESTART_FLAGS_SIZE + TIMER_SIZE + (AFI_SIZE * Byte.SIZE + SAFI_SIZE * Byte.SIZE + AF_FLAGS_SIZE
105 * param.getTableTypes().size())
107 if (param.isRestartFlag())
108 bytes[0] = (byte) 0x80;
109 int index = (RESTART_FLAGS_SIZE + TIMER_SIZE) / Byte.SIZE;
110 for (final Entry<BGPTableType, Boolean> entry : param.getTableTypes().entrySet()) {
111 final byte[] a = putAfi(entry.getKey().getAddressFamily());
112 final byte s = putSafi(entry.getKey().getSubsequentAddressFamily());
113 final byte f = (entry.getValue()) ? (byte) 0x80 : (byte) 0x00;
114 System.arraycopy(a, 0, bytes, index, AFI_SIZE);
119 index += AF_FLAGS_SIZE;
124 private static byte[] putMultiProtocolParameterValue(final MultiprotocolCapability param) {
125 final byte[] a = putAfi(param.getAfi());
126 final byte s = putSafi(param.getSafi());
128 final byte[] bytes = new byte[AFI_SIZE + SAFI_SIZE + 1]; // 2 byte is reserved 2B AFI + 1B Reserved + 1B SAFI
129 System.arraycopy(a, 0, bytes, 0, AFI_SIZE);
130 bytes[AFI_SIZE + 1] = s; // +1 = reserved
134 private static byte[] putAS4BytesParameterValue(final AS4BytesCapability param) {
135 return ByteArray.subByte(ByteArray.longToBytes(param.getASNumber().getAsn()), 4, 4);
138 private static MultiprotocolCapability parseMultiProtocolParameterValue(final byte[] bytes) throws BGPParsingException {
139 final BGPAddressFamily afi = MPReachParser.parseAfi(ByteArray.bytesToInt(ByteArray.subByte(bytes, 0, AFI_SIZE)));
140 final BGPSubsequentAddressFamily safi = MPReachParser.parseSafi(ByteArray.bytesToInt(ByteArray.subByte(bytes, AFI_SIZE + 1,
142 return new MultiprotocolCapability(new BGPTableType(afi, safi));
145 private static AS4BytesCapability parseAS4BParameterValue(final byte[] bytes) {
146 return new AS4BytesCapability(new ASNumber(ByteArray.bytesToLong(bytes)));
149 static byte[] putAfi(final BGPAddressFamily afi) {
150 final byte[] a = ByteArray.intToBytes(serializeAfi(afi));
151 return ByteArray.subByte(a, Integer.SIZE / Byte.SIZE - AFI_SIZE, AFI_SIZE);
154 static byte putSafi(final BGPSubsequentAddressFamily safi) {
155 final byte[] a = ByteArray.intToBytes(serializeSafi(safi));
156 return ByteArray.subByte(a, Integer.SIZE / Byte.SIZE - SAFI_SIZE, SAFI_SIZE)[0];
159 private static int serializeSafi(final BGPSubsequentAddressFamily type) {
166 return MPReachParser.LS_SAFI;
171 private static int serializeAfi(final BGPAddressFamily type) {
178 return MPReachParser.LS_AFI;