5faad29fc26b50e6a9ca93c8bf972ebc5da0b869
[bgpcep.git] / bgp / parser-spi / src / main / java / org / opendaylight / protocol / bgp / parser / spi / pojo / SimpleAttributeRegistry.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.protocol.bgp.parser.spi.pojo;
9
10 import com.google.common.base.Preconditions;
11 import com.google.common.primitives.UnsignedBytes;
12
13 import io.netty.buffer.ByteBuf;
14
15 import java.util.Map;
16 import java.util.Map.Entry;
17 import java.util.TreeMap;
18
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;
34
35 final class SimpleAttributeRegistry implements AttributeRegistry {
36     private static final class RawAttribute {
37         private final AttributeParser parser;
38         private final ByteBuf buffer;
39
40         public RawAttribute(final AttributeParser parser, final ByteBuf buffer) {
41             this.parser = Preconditions.checkNotNull(parser);
42             this.buffer = Preconditions.checkNotNull(buffer);
43         }
44     }
45
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<>();
52
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);
56     }
57
58     AutoCloseable registerAttributeSerializer(final Class<? extends DataObject> paramClass, final AttributeSerializer serializer) {
59         return this.handlers.registerSerializer(paramClass, serializer);
60     }
61
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());
65         final int hdrlen;
66         final int len;
67         if (flags[EXTENDED_LENGTH_BIT]) {
68             len = UnsignedBytes.toInt(buffer.readByte()) * 256 + UnsignedBytes.toInt(buffer.readByte());
69             hdrlen = 4;
70         } else {
71             len = UnsignedBytes.toInt(buffer.readByte());
72             hdrlen = 3;
73         }
74         if (!attributes.containsKey(type)) {
75             final AttributeParser parser = this.handlers.getParser(type);
76             if (parser == null) {
77                 if (!flags[OPTIONAL_BIT]) {
78                     throw new BGPDocumentedException("Well known attribute not recognized.", BGPError.WELL_KNOWN_ATTR_NOT_RECOGNIZED);
79                 }
80                 if (flags[TRANSITIVE_BIT]) {
81                     // FIXME: transitive attributes need to be preserved
82                     LOG.warn("Losing unrecognized transitive attribute {}", type);
83                 } else {
84                     LOG.debug("Ignoring unrecognized attribute type {}", type);
85                 }
86             } else {
87                 attributes.put(type, new RawAttribute(parser, buffer.slice(buffer.readerIndex(), len)));
88                 buffer.skipBytes(len);
89             }
90         } else {
91             LOG.debug("Ignoring duplicate attribute type {}", type);
92         }
93         return hdrlen + len;
94     }
95
96     @Override
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);
101         }
102         /*
103          * TreeMap guarantees that we will be invoking the parser in the order
104          * of increasing attribute type.
105          */
106         final PathAttributesBuilder builder = new PathAttributesBuilder();
107         for (final Entry<Integer, RawAttribute> e : attributes.entrySet()) {
108             LOG.debug("Parsing attribute type {}", e.getKey());
109
110             final RawAttribute a = e.getValue();
111             a.parser.parseAttribute(a.buffer, builder);
112         }
113
114         return builder.build();
115     }
116
117     @Override
118     public byte[] serializeAttribute(final DataObject attribute) {
119         final AttributeSerializer serializer = this.handlers.getSerializer(attribute.getImplementedInterface());
120         if (serializer == null) {
121             return null;
122         }
123         return serializer.serializeAttribute(attribute);
124     }
125 }