Reduce noise from BGPSessionImpl
[bgpcep.git] / bgp / extensions / linkstate / src / main / java / org / opendaylight / protocol / bgp / linkstate / impl / attribute / LinkstateAttributeParser.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.linkstate.impl.attribute;
9
10 import com.google.common.collect.HashMultimap;
11 import com.google.common.collect.Multimap;
12 import io.netty.buffer.ByteBuf;
13 import io.netty.buffer.Unpooled;
14 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
15 import org.opendaylight.protocol.bgp.parser.spi.AbstractAttributeParser;
16 import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
17 import org.opendaylight.protocol.bgp.parser.spi.AttributeUtil;
18 import org.opendaylight.protocol.bgp.parser.spi.PeerSpecificParserConstraint;
19 import org.opendaylight.protocol.bgp.parser.spi.RevisedErrorHandling;
20 import org.opendaylight.protocol.rsvp.parser.spi.RSVPTeObjectRegistry;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.Attributes1;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.Attributes1Builder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.ProtocolId;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.ObjectType;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.destination.CLinkstateDestination;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.LinkCase;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.NodeCase;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.PrefixCase;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.TeLspCase;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.LinkStateAttribute;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.LinkAttributesCase;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.NodeAttributesCase;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.PrefixAttributesCase;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.path.attribute.link.state.attribute.TeLspAttributesCase;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.Attributes;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.AttributesBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.AttributesReach;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.AttributesUnreach;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.destination.DestinationType;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 /**
45  * Parser for Link State Path Attribute.
46  *
47  * @see <a href="http://tools.ietf.org/html/draft-gredler-idr-ls-distribution-04">BGP-LS draft</a>
48  */
49 public final class LinkstateAttributeParser extends AbstractAttributeParser implements AttributeSerializer {
50
51     private static final Logger LOG = LoggerFactory.getLogger(LinkstateAttributeParser.class);
52
53     private static final int TYPE = 29;
54
55     private static final int LEGACY_TYPE = 99;
56
57     private final int type;
58
59     private final RSVPTeObjectRegistry rsvpTeObjectRegistry;
60
61     public LinkstateAttributeParser(final boolean isIanaAssignedType, final RSVPTeObjectRegistry rsvpTeObjectRegistry) {
62         this.type = isIanaAssignedType ? TYPE : LEGACY_TYPE;
63         this.rsvpTeObjectRegistry = rsvpTeObjectRegistry;
64     }
65
66     private static Multimap<Integer, ByteBuf> getAttributesMap(final ByteBuf buffer) {
67         /*
68          * e.g. IS-IS Area Identifier TLV can occur multiple times
69          */
70         final Multimap<Integer, ByteBuf> map = HashMultimap.create();
71         while (buffer.isReadable()) {
72             final int type = buffer.readUnsignedShort();
73             final int length = buffer.readUnsignedShort();
74             final ByteBuf value = buffer.readSlice(length);
75             map.put(type, value);
76         }
77         return map;
78     }
79
80     public int getType() {
81         return this.type;
82     }
83
84     @Override
85     public void parseAttribute(final ByteBuf buffer, final AttributesBuilder builder,
86             final RevisedErrorHandling errorHandling, final PeerSpecificParserConstraint constraint)
87                     throws BGPParsingException {
88         // FIXME: BGPCEP-359: we need an updated link-state spec for RFC7606
89         final CLinkstateDestination lsDestination = getNlriType(builder);
90         if (lsDestination == null) {
91             LOG.warn("No Linkstate NLRI found, not parsing Linkstate attribute");
92             return;
93         }
94         final ObjectType nlriType = lsDestination.getObjectType();
95         final ProtocolId protocolId = lsDestination.getProtocolId();
96         builder.addAugmentation(new Attributes1Builder()
97             .setLinkStateAttribute(parseLinkState(nlriType, protocolId, buffer))
98             .build());
99     }
100
101     private static CLinkstateDestination getNlriType(final AttributesBuilder pab) {
102         final AttributesReach mpr = pab.augmentation(AttributesReach.class);
103         if (mpr != null && mpr.getMpReachNlri() != null) {
104             final DestinationType dt = mpr.getMpReachNlri().getAdvertizedRoutes().getDestinationType();
105             if (dt instanceof DestinationLinkstateCase) {
106                 for (final CLinkstateDestination d : ((DestinationLinkstateCase) dt).getDestinationLinkstate()
107                         .getCLinkstateDestination()) {
108                     return d;
109                 }
110             }
111         }
112         final AttributesUnreach mpu = pab.augmentation(AttributesUnreach.class);
113         if (mpu != null && mpu.getMpUnreachNlri() != null) {
114             final DestinationType dt = mpu.getMpUnreachNlri().getWithdrawnRoutes().getDestinationType();
115             if (dt instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120
116                     .update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationLinkstateCase) {
117                 for (final CLinkstateDestination d : ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang
118                         .bgp.linkstate.rev200120.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type
119                         .DestinationLinkstateCase) dt).getDestinationLinkstate().getCLinkstateDestination()) {
120                     return d;
121                 }
122             }
123         }
124         return null;
125     }
126
127     private LinkStateAttribute parseLinkState(final ObjectType nlri, final ProtocolId protocolId, final ByteBuf buffer)
128             throws BGPParsingException {
129         if (nlri instanceof PrefixCase) {
130             return PrefixAttributesParser.parsePrefixAttributes(getAttributesMap(buffer), protocolId);
131         } else if (nlri instanceof LinkCase) {
132             return LinkAttributesParser.parseLinkAttributes(getAttributesMap(buffer), protocolId);
133         } else if (nlri instanceof NodeCase) {
134             return NodeAttributesParser.parseNodeAttributes(getAttributesMap(buffer), protocolId);
135         } else if (nlri instanceof TeLspCase) {
136             return TeLspAttributesParser.parseTeLspAttributes(this.rsvpTeObjectRegistry, getAttributesMap(buffer)
137                 .entries().iterator().next().getValue());
138         } else {
139             throw new IllegalStateException("Unhandled NLRI type " + nlri);
140         }
141     }
142
143     /**
144      * Serialize linkstate attributes.
145      *
146      * @param attribute DataObject representing LinkstatePathAttribute
147      * @param byteAggregator ByteBuf where all serialized data are aggregated
148      */
149
150     @Override
151     public void serializeAttribute(final Attributes attribute, final ByteBuf byteAggregator) {
152         final Attributes1 pathAttributes1 = attribute.augmentation(Attributes1.class);
153         if (pathAttributes1 == null) {
154             return;
155         }
156         final LinkStateAttribute linkState = pathAttributes1.getLinkStateAttribute();
157         final ByteBuf lsBuffer = Unpooled.buffer();
158         if (linkState instanceof LinkAttributesCase) {
159             LinkAttributesParser.serializeLinkAttributes((LinkAttributesCase) linkState, lsBuffer);
160         } else if (linkState instanceof NodeAttributesCase) {
161             NodeAttributesParser.serializeNodeAttributes((NodeAttributesCase) linkState, lsBuffer);
162         } else if (linkState instanceof PrefixAttributesCase) {
163             PrefixAttributesParser.serializePrefixAttributes((PrefixAttributesCase) linkState, lsBuffer);
164         } else if (linkState instanceof TeLspAttributesCase) {
165             TeLspAttributesParser.serializeLspAttributes(this.rsvpTeObjectRegistry, (TeLspAttributesCase) linkState,
166                 lsBuffer);
167             byteAggregator.writeBytes(lsBuffer);
168             return;
169         }
170         AttributeUtil.formatAttribute(AttributeUtil.OPTIONAL, getType(), lsBuffer, byteAggregator);
171     }
172 }