15e5e0fcb356b9d0d0f8fd321a301ca8b2e8b8c8
[bgpcep.git] / bgp / linkstate / src / main / java / org / opendaylight / protocol / bgp / linkstate / 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.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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.NlriType;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.PathAttributes1;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.PathAttributes1Builder;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.linkstate.destination.CLinkstateDestination;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.LinkstatePathAttribute;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.LinkstatePathAttributeBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.linkstate.path.attribute.LinkStateAttribute;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.linkstate.path.attribute.link.state.attribute.LinkAttributesCase;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.linkstate.path.attribute.link.state.attribute.NodeAttributesCase;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.linkstate.path.attribute.link.state.attribute.PrefixAttributesCase;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributes;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributesBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes2;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.destination.DestinationType;
34 import org.opendaylight.yangtools.yang.binding.DataObject;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 /**
39  * Parser for Link State Path Attribute.
40  *
41  * @see <a href="http://tools.ietf.org/html/draft-gredler-idr-ls-distribution-04">BGP-LS draft</a>
42  */
43 public class LinkstateAttributeParser implements AttributeParser, AttributeSerializer {
44
45     private static final Logger LOG = LoggerFactory.getLogger(LinkstateAttributeParser.class);
46
47     private static final int TYPE = 29;
48
49     private static final int LEGACY_TYPE = 99;
50
51     private final int type;
52
53     public LinkstateAttributeParser(final boolean isIanaAssignedType) {
54         this.type = (isIanaAssignedType) ? TYPE : LEGACY_TYPE;
55     }
56
57     public int getType() {
58         return this.type;
59     }
60
61     @Override
62     public void parseAttribute(final ByteBuf buffer, final PathAttributesBuilder builder) throws BGPParsingException {
63         final NlriType nlriType = getNlriType(builder);
64         if (nlriType == null) {
65             LOG.warn("No Linkstate NLRI found, not parsing Linkstate attribute");
66             return;
67         }
68         final PathAttributes1 a = new PathAttributes1Builder().setLinkstatePathAttribute(parseLinkState(nlriType, buffer)).build();
69         builder.addAugmentation(PathAttributes1.class, a);
70     }
71
72     private NlriType getNlriType(final PathAttributesBuilder pab) {
73         final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes1 mpr = pab.getAugmentation(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes1.class);
74         if (mpr != null && mpr.getMpReachNlri() != null) {
75             final DestinationType dt = mpr.getMpReachNlri().getAdvertizedRoutes().getDestinationType();
76             if (dt instanceof DestinationLinkstateCase) {
77                 for (final CLinkstateDestination d : ((DestinationLinkstateCase) dt).getDestinationLinkstate().getCLinkstateDestination()) {
78                     return d.getNlriType();
79                 }
80             }
81         }
82         final PathAttributes2 mpu = pab.getAugmentation(PathAttributes2.class);
83         if (mpu != null && mpu.getMpUnreachNlri() != null) {
84             final DestinationType dt = mpu.getMpUnreachNlri().getWithdrawnRoutes().getDestinationType();
85             if (dt instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationLinkstateCase) {
86                 for (final CLinkstateDestination d : ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev131125.update.path.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationLinkstateCase) dt).getDestinationLinkstate().getCLinkstateDestination()) {
87                     return d.getNlriType();
88                 }
89             }
90         }
91         return null;
92     }
93
94     private static LinkstatePathAttribute parseLinkState(final NlriType nlri, final ByteBuf buffer) throws BGPParsingException {
95         /*
96          * e.g. IS-IS Area Identifier TLV can occur multiple times
97          */
98         final Multimap<Integer, ByteBuf> map = HashMultimap.create();
99         while (buffer.isReadable()) {
100             final int type = buffer.readUnsignedShort();
101             final int length = buffer.readUnsignedShort();
102             final ByteBuf value = buffer.slice(buffer.readerIndex(), length);
103             map.put(type, value);
104             buffer.skipBytes(length);
105         }
106         final LinkstatePathAttributeBuilder builder = new LinkstatePathAttributeBuilder();
107
108         switch (nlri) {
109         case Ipv4Prefix:
110         case Ipv6Prefix:
111             builder.setLinkStateAttribute(PrefixAttributesParser.parsePrefixAttributes(map));
112             return builder.build();
113         case Link:
114             builder.setLinkStateAttribute(LinkAttributesParser.parseLinkAttributes(map));
115             return builder.build();
116         case Node:
117             builder.setLinkStateAttribute(NodeAttributesParser.parseNodeAttributes(map));
118             return builder.build();
119         default:
120             throw new IllegalStateException("Unhandled NLRI type " + nlri);
121         }
122     }
123
124     /**
125      * Serialize linkstate attributes.
126      *
127      * @param attribute DataObject representing LinkstatePathAttribute
128      * @param byteAggregator ByteBuf where all serialized data are aggregated
129      */
130
131     @Override
132     public void serializeAttribute(final DataObject attribute, final ByteBuf byteAggregator) {
133         Preconditions.checkArgument(attribute instanceof PathAttributes, "Attribute parameter is not a PathAttribute object.");
134         final PathAttributes1 pathAttributes1 = ((PathAttributes) attribute).getAugmentation(PathAttributes1.class);
135         if (pathAttributes1 == null) {
136             return;
137         }
138         final LinkStateAttribute linkState = pathAttributes1.getLinkstatePathAttribute().getLinkStateAttribute();
139         final ByteBuf lsBuffer = Unpooled.buffer();
140         if (linkState instanceof LinkAttributesCase) {
141             LinkAttributesParser.serializeLinkAttributes((LinkAttributesCase) linkState, lsBuffer);
142         } else if (linkState instanceof NodeAttributesCase) {
143             NodeAttributesParser.serializeNodeAttributes((NodeAttributesCase) linkState, lsBuffer);
144         } else if (linkState instanceof PrefixAttributesCase) {
145             PrefixAttributesParser.serializePrefixAttributes((PrefixAttributesCase) linkState, lsBuffer);
146         }
147         AttributeUtil.formatAttribute(AttributeUtil.OPTIONAL, getType(), lsBuffer, byteAggregator);
148     }
149 }