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