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.spi.pojo;
10 import com.google.common.base.Preconditions;
11 import com.google.common.primitives.UnsignedBytes;
13 import io.netty.buffer.ByteBuf;
16 import java.util.Map.Entry;
17 import java.util.TreeMap;
19 import org.opendaylight.protocol.bgp.parser.BGPDocumentedException;
20 import org.opendaylight.protocol.bgp.parser.BGPError;
21 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
22 import org.opendaylight.protocol.bgp.parser.spi.AttributeParser;
23 import org.opendaylight.protocol.bgp.parser.spi.AttributeRegistry;
24 import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
25 import org.opendaylight.protocol.concepts.HandlerRegistry;
26 import org.opendaylight.protocol.util.ByteArray;
27 import org.opendaylight.protocol.util.Values;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributes;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributesBuilder;
30 import org.opendaylight.yangtools.yang.binding.DataContainer;
31 import org.opendaylight.yangtools.yang.binding.DataObject;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
35 final class SimpleAttributeRegistry implements AttributeRegistry {
36 private static final class RawAttribute {
37 private final AttributeParser parser;
38 private final ByteBuf buffer;
40 public RawAttribute(final AttributeParser parser, final ByteBuf buffer) {
41 this.parser = Preconditions.checkNotNull(parser);
42 this.buffer = Preconditions.checkNotNull(buffer);
46 private static final Logger LOG = LoggerFactory.getLogger(SimpleAttributeRegistry.class);
47 private static final int OPTIONAL_BIT = 0;
48 private static final int TRANSITIVE_BIT = 1;
49 private static final int PARTIAL_BIT = 2;
50 private static final int EXTENDED_LENGTH_BIT = 3;
51 private final HandlerRegistry<DataContainer, AttributeParser, AttributeSerializer> handlers = new HandlerRegistry<>();
53 AutoCloseable registerAttributeParser(final int attributeType, final AttributeParser parser) {
54 Preconditions.checkArgument(attributeType >= 0 && attributeType <= Values.UNSIGNED_BYTE_MAX_VALUE);
55 return this.handlers.registerParser(attributeType, parser);
58 AutoCloseable registerAttributeSerializer(final Class<? extends DataObject> paramClass, final AttributeSerializer serializer) {
59 return this.handlers.registerSerializer(paramClass, serializer);
62 private int addAttribute(final ByteBuf buffer, final Map<Integer, RawAttribute> attributes) throws BGPDocumentedException {
63 final boolean[] flags = ByteArray.parseBits(buffer.readByte());
64 final Integer type = UnsignedBytes.toInt(buffer.readByte());
67 if (flags[EXTENDED_LENGTH_BIT]) {
68 len = UnsignedBytes.toInt(buffer.readByte()) * 256 + UnsignedBytes.toInt(buffer.readByte());
71 len = UnsignedBytes.toInt(buffer.readByte());
74 if (!attributes.containsKey(type)) {
75 final AttributeParser parser = this.handlers.getParser(type);
77 if (!flags[OPTIONAL_BIT]) {
78 throw new BGPDocumentedException("Well known attribute not recognized.", BGPError.WELL_KNOWN_ATTR_NOT_RECOGNIZED);
80 if (flags[TRANSITIVE_BIT]) {
81 // FIXME: transitive attributes need to be preserved
82 LOG.warn("Losing unrecognized transitive attribute {}", type);
84 LOG.debug("Ignoring unrecognized attribute type {}", type);
87 attributes.put(type, new RawAttribute(parser, buffer.slice(buffer.readerIndex(), len)));
88 buffer.skipBytes(len);
91 LOG.debug("Ignoring duplicate attribute type {}", type);
97 public PathAttributes parseAttributes(final ByteBuf buffer) throws BGPDocumentedException, BGPParsingException {
98 final TreeMap<Integer, RawAttribute> attributes = new TreeMap<>();
99 while (buffer.readableBytes() != 0) {
100 addAttribute(buffer, attributes);
103 * TreeMap guarantees that we will be invoking the parser in the order
104 * of increasing attribute type.
106 final PathAttributesBuilder builder = new PathAttributesBuilder();
107 for (final Entry<Integer, RawAttribute> e : attributes.entrySet()) {
108 LOG.debug("Parsing attribute type {}", e.getKey());
110 final RawAttribute a = e.getValue();
111 a.parser.parseAttribute(a.buffer, builder);
114 return builder.build();
118 public byte[] serializeAttribute(final DataObject attribute) {
119 final AttributeSerializer serializer = this.handlers.getSerializer(attribute.getImplementedInterface());
120 if (serializer == null) {
123 return serializer.serializeAttribute(attribute);