0f15dad1a28ad694b74710070d1796b95a238a9c
[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
14 import io.netty.buffer.ByteBuf;
15 import io.netty.buffer.Unpooled;
16
17 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
18 import org.opendaylight.protocol.bgp.parser.spi.AttributeParser;
19 import org.opendaylight.protocol.bgp.parser.spi.AttributeSerializer;
20 import org.opendaylight.protocol.bgp.parser.spi.AttributeUtil;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.PathAttributes1;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.PathAttributes1Builder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.ObjectType;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.destination.CLinkstateDestination;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.LinkCase;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.NodeCase;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.PrefixCase;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.LinkstatePathAttribute;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.LinkstatePathAttributeBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.linkstate.path.attribute.LinkStateAttribute;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.linkstate.path.attribute.link.state.attribute.LinkAttributesCase;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.linkstate.path.attribute.link.state.attribute.NodeAttributesCase;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.linkstate.path.attribute.link.state.attribute.PrefixAttributesCase;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributes;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributesBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes2;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.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 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     public LinkstateAttributeParser(final boolean isIanaAssignedType) {
59         this.type = (isIanaAssignedType) ? TYPE : LEGACY_TYPE;
60     }
61
62     public int getType() {
63         return this.type;
64     }
65
66     @Override
67     public void parseAttribute(final ByteBuf buffer, final PathAttributesBuilder builder) throws BGPParsingException {
68         final ObjectType nlriType = getNlriType(builder);
69         if (nlriType == null) {
70             LOG.warn("No Linkstate NLRI found, not parsing Linkstate attribute");
71             return;
72         }
73         final PathAttributes1 a = new PathAttributes1Builder().setLinkstatePathAttribute(parseLinkState(nlriType, buffer)).build();
74         builder.addAugmentation(PathAttributes1.class, a);
75     }
76
77     private ObjectType getNlriType(final PathAttributesBuilder pab) {
78         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);
79         if (mpr != null && mpr.getMpReachNlri() != null) {
80             final DestinationType dt = mpr.getMpReachNlri().getAdvertizedRoutes().getDestinationType();
81             if (dt instanceof DestinationLinkstateCase) {
82                 for (final CLinkstateDestination d : ((DestinationLinkstateCase) dt).getDestinationLinkstate().getCLinkstateDestination()) {
83                     return d.getObjectType();
84                 }
85             }
86         }
87         final PathAttributes2 mpu = pab.getAugmentation(PathAttributes2.class);
88         if (mpu != null && mpu.getMpUnreachNlri() != null) {
89             final DestinationType dt = mpu.getMpUnreachNlri().getWithdrawnRoutes().getDestinationType();
90             if (dt instanceof org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationLinkstateCase) {
91                 for (final CLinkstateDestination d : ((org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationLinkstateCase) dt).getDestinationLinkstate().getCLinkstateDestination()) {
92                     return d.getObjectType();
93                 }
94             }
95         }
96         return null;
97     }
98
99     private static LinkstatePathAttribute parseLinkState(final ObjectType nlri, final ByteBuf buffer) throws BGPParsingException {
100         /*
101          * e.g. IS-IS Area Identifier TLV can occur multiple times
102          */
103         final Multimap<Integer, ByteBuf> map = HashMultimap.create();
104         while (buffer.isReadable()) {
105             final int type = buffer.readUnsignedShort();
106             final int length = buffer.readUnsignedShort();
107             final ByteBuf value = buffer.readSlice(length);
108             map.put(type, value);
109         }
110         final LinkstatePathAttributeBuilder builder = new LinkstatePathAttributeBuilder();
111         if (nlri instanceof PrefixCase) {
112             builder.setLinkStateAttribute(PrefixAttributesParser.parsePrefixAttributes(map));
113             return builder.build();
114         } else if (nlri instanceof LinkCase) {
115             builder.setLinkStateAttribute(LinkAttributesParser.parseLinkAttributes(map));
116             return builder.build();
117         } else if (nlri instanceof NodeCase) {
118             builder.setLinkStateAttribute(NodeAttributesParser.parseNodeAttributes(map));
119             return builder.build();
120         } else {
121             throw new IllegalStateException("Unhandled NLRI type " + nlri);
122         }
123     }
124
125     /**
126      * Serialize linkstate attributes.
127      *
128      * @param attribute DataObject representing LinkstatePathAttribute
129      * @param byteAggregator ByteBuf where all serialized data are aggregated
130      */
131
132     @Override
133     public void serializeAttribute(final DataObject attribute, final ByteBuf byteAggregator) {
134         Preconditions.checkArgument(attribute instanceof PathAttributes, "Attribute parameter is not a PathAttribute object.");
135         final PathAttributes1 pathAttributes1 = ((PathAttributes) attribute).getAugmentation(PathAttributes1.class);
136         if (pathAttributes1 == null) {
137             return;
138         }
139         final LinkStateAttribute linkState = pathAttributes1.getLinkstatePathAttribute().getLinkStateAttribute();
140         final ByteBuf lsBuffer = Unpooled.buffer();
141         if (linkState instanceof LinkAttributesCase) {
142             LinkAttributesParser.serializeLinkAttributes((LinkAttributesCase) linkState, lsBuffer);
143         } else if (linkState instanceof NodeAttributesCase) {
144             NodeAttributesParser.serializeNodeAttributes((NodeAttributesCase) linkState, lsBuffer);
145         } else if (linkState instanceof PrefixAttributesCase) {
146             PrefixAttributesParser.serializePrefixAttributes((PrefixAttributesCase) linkState, lsBuffer);
147         }
148         AttributeUtil.formatAttribute(AttributeUtil.OPTIONAL, getType(), lsBuffer, byteAggregator);
149     }
150 }