2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.protocol.bgp.linkstate.nlri;
10 import com.google.common.base.Preconditions;
11 import io.netty.buffer.ByteBuf;
12 import io.netty.buffer.Unpooled;
13 import java.math.BigInteger;
14 import java.util.ArrayList;
15 import java.util.List;
16 import org.opendaylight.protocol.bgp.linkstate.spi.TlvUtil;
17 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
18 import org.opendaylight.protocol.bgp.parser.spi.NlriParser;
19 import org.opendaylight.protocol.bgp.parser.spi.NlriSerializer;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.Identifier;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.NlriType;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.NodeIdentifier;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.ProtocolId;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.RouteDistinguisher;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.ObjectType;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.destination.CLinkstateDestination;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.destination.CLinkstateDestinationBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.LinkCase;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.LinkCaseBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.NodeCase;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.NodeCaseBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.PrefixCase;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.PrefixCaseBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.link._case.LocalNodeDescriptors;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.link._case.RemoteNodeDescriptors;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.node._case.NodeDescriptors;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.prefix._case.AdvertisingNodeDescriptors;
38 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.DestinationLinkstateCaseBuilder;
39 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.destination.linkstate._case.DestinationLinkstateBuilder;
40 import 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;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.update.PathAttributes;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes1;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.PathAttributes2;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpReachNlriBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpUnreachNlri;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.MpUnreachNlriBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.mp.reach.nlri.AdvertizedRoutes;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.path.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
50 import org.opendaylight.yangtools.yang.binding.DataObject;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
55 * Parser and serializer for Linkstate NLRI.
57 public final class LinkstateNlriParser implements NlriParser, NlriSerializer {
58 private static final Logger LOG = LoggerFactory.getLogger(LinkstateNlriParser.class);
59 private static final int ROUTE_DISTINGUISHER_LENGTH = 8;
60 private static final int PROTOCOL_ID_LENGTH = 1;
61 private static final int IDENTIFIER_LENGTH = 8;
63 private static final int TYPE_LENGTH = 2;
64 private static final int LENGTH_SIZE = 2;
67 private static final int LOCAL_NODE_DESCRIPTORS = 256;
68 private static final int REMOTE_NODE_DESCRIPTORS = 257;
70 private final boolean isVpn;
72 public LinkstateNlriParser(final boolean isVpn) {
76 private static NodeIdentifier parseLink(final CLinkstateDestinationBuilder builder, final ByteBuf buffer, final LocalNodeDescriptors localDescriptors)
77 throws BGPParsingException {
78 final int type = buffer.readUnsignedShort();
79 final int length = buffer.readUnsignedShort();
80 final NodeIdentifier remote = null;
81 RemoteNodeDescriptors remoteDescriptors = null;
82 if (type == REMOTE_NODE_DESCRIPTORS) {
83 remoteDescriptors = (RemoteNodeDescriptors)NodeNlriParser.parseNodeDescriptors(buffer.readSlice(length), NlriType.Link, false);
85 builder.setObjectType(new LinkCaseBuilder()
86 .setLocalNodeDescriptors(localDescriptors)
87 .setRemoteNodeDescriptors(remoteDescriptors)
88 .setLinkDescriptors(LinkNlriParser.parseLinkDescriptors(buffer.slice())).build());
93 * Parses common parts for Link State Nodes, Links and Prefixes, that includes protocol ID and identifier tlv.
95 * @param nlri as byte array
96 * @param isVpn flag which determines that destination has route distinguisher
97 * @return {@link CLinkstateDestination}
98 * @throws BGPParsingException if parsing was unsuccessful
100 public static List<CLinkstateDestination> parseNlri(final ByteBuf nlri, final boolean isVpn) throws BGPParsingException {
101 final List<CLinkstateDestination> dests = new ArrayList<>();
102 while (nlri.isReadable()) {
103 final CLinkstateDestinationBuilder builder = new CLinkstateDestinationBuilder();
104 final NlriType type = NlriType.forValue(nlri.readUnsignedShort());
106 // length means total length of the tlvs including route distinguisher not including the type field
107 final int length = nlri.readUnsignedShort();
108 RouteDistinguisher distinguisher = null;
110 // this parses route distinguisher
111 distinguisher = new RouteDistinguisher(BigInteger.valueOf(nlri.readLong()));
112 builder.setDistinguisher(distinguisher);
114 // parse source protocol
115 final ProtocolId sp = ProtocolId.forValue(nlri.readByte());
116 builder.setProtocolId(sp);
119 final Identifier identifier = new Identifier(BigInteger.valueOf(nlri.readLong()));
120 builder.setIdentifier(identifier);
122 // if we are dealing with linkstate nodes/links, parse local node descriptor
123 NodeIdentifier localDescriptor = null;
124 final int localtype = nlri.readUnsignedShort();
125 final int locallength = nlri.readUnsignedShort();
126 if (localtype == LOCAL_NODE_DESCRIPTORS) {
127 localDescriptor = NodeNlriParser.parseNodeDescriptors(nlri.readSlice(locallength), type, true);
129 final int restLength = length - (isVpn ? ROUTE_DISTINGUISHER_LENGTH : 0) - PROTOCOL_ID_LENGTH - IDENTIFIER_LENGTH
130 - TYPE_LENGTH - LENGTH_SIZE - locallength;
131 LOG.trace("Restlength {}", restLength);
132 final ByteBuf rest = nlri.readSlice(restLength);
135 parseLink(builder, rest, (LocalNodeDescriptors) localDescriptor);
138 builder.setObjectType(new PrefixCaseBuilder()
139 .setAdvertisingNodeDescriptors((AdvertisingNodeDescriptors)localDescriptor)
140 .setPrefixDescriptors(PrefixNlriParser.parsePrefixDescriptors(rest, true)).build());
143 builder.setObjectType(new PrefixCaseBuilder()
144 .setAdvertisingNodeDescriptors((AdvertisingNodeDescriptors)localDescriptor)
145 .setPrefixDescriptors(PrefixNlriParser.parsePrefixDescriptors(rest, false)).build());
148 // node nlri is already parsed as it contains only the common fields for node and link nlri
149 builder.setObjectType(new NodeCaseBuilder().setNodeDescriptors((NodeDescriptors)localDescriptor).build());
154 dests.add(builder.build());
160 public void parseNlri(final ByteBuf nlri, final MpUnreachNlriBuilder builder) throws BGPParsingException {
161 if (!nlri.isReadable()) {
164 final List<CLinkstateDestination> dst = parseNlri(nlri, this.isVpn);
166 builder.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(
167 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationLinkstateCaseBuilder().setDestinationLinkstate(
168 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.path.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.linkstate._case.DestinationLinkstateBuilder().setCLinkstateDestination(
169 dst).build()).build()).build());
173 public void parseNlri(final ByteBuf nlri, final MpReachNlriBuilder builder) throws BGPParsingException {
174 if (!nlri.isReadable()) {
177 final List<CLinkstateDestination> dst = parseNlri(nlri, this.isVpn);
179 builder.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(
180 new DestinationLinkstateCaseBuilder().setDestinationLinkstate(
181 new DestinationLinkstateBuilder().setCLinkstateDestination(dst).build()).build()).build());
185 * Serializes Linkstate NLRI to byte array. We need this as NLRI serves as a key in upper layers.
187 * @param destination Linkstate NLRI to be serialized
188 * @param buffer where Linkstate NLRI will be serialized
190 public static void serializeNlri(final CLinkstateDestination destination, final ByteBuf buffer) {
191 final ByteBuf nlriByteBuf = Unpooled.buffer();
192 if (destination.getDistinguisher() != null) {
193 nlriByteBuf.writeBytes(destination.getDistinguisher().getValue().toByteArray());
195 nlriByteBuf.writeByte(destination.getProtocolId().getIntValue());
196 nlriByteBuf.writeLong(destination.getIdentifier().getValue().longValue());
197 final ByteBuf ldescs = Unpooled.buffer();
198 final ObjectType ot = destination.getObjectType();
199 NlriType nlriType = null;
200 if (ot instanceof PrefixCase) {
201 final PrefixCase pCase = (PrefixCase)destination.getObjectType();
202 NodeNlriParser.serializeNodeDescriptors(pCase.getAdvertisingNodeDescriptors(), ldescs);
203 TlvUtil.writeTLV(LOCAL_NODE_DESCRIPTORS, ldescs, nlriByteBuf);
204 if (pCase.getPrefixDescriptors() != null) {
205 PrefixNlriParser.serializePrefixDescriptors(pCase.getPrefixDescriptors(), nlriByteBuf);
206 if (pCase.getPrefixDescriptors().getIpReachabilityInformation().getIpv4Prefix() != null) {
207 nlriType = NlriType.Ipv4Prefix;
209 nlriType = NlriType.Ipv6Prefix;
212 } else if (ot instanceof LinkCase) {
213 final LinkCase lCase = (LinkCase)destination.getObjectType();
214 NodeNlriParser.serializeNodeDescriptors(lCase.getLocalNodeDescriptors(), ldescs);
215 TlvUtil.writeTLV(LOCAL_NODE_DESCRIPTORS, ldescs, nlriByteBuf);
216 final ByteBuf rdescs = Unpooled.buffer();
217 NodeNlriParser.serializeNodeDescriptors(lCase.getRemoteNodeDescriptors(), rdescs);
218 TlvUtil.writeTLV(REMOTE_NODE_DESCRIPTORS, rdescs, nlriByteBuf);
219 if (lCase.getLinkDescriptors() != null) {
220 LinkNlriParser.serializeLinkDescriptors(lCase.getLinkDescriptors(), nlriByteBuf);
222 nlriType = NlriType.Link;
223 } else if (ot instanceof NodeCase) {
224 final NodeCase nCase = (NodeCase)destination.getObjectType();
225 NodeNlriParser.serializeNodeDescriptors(nCase.getNodeDescriptors(), ldescs);
226 TlvUtil.writeTLV(LOCAL_NODE_DESCRIPTORS, ldescs, nlriByteBuf);
227 nlriType = NlriType.Node;
229 LOG.warn("Unknown NLRI Type.");
231 TlvUtil.writeTLV(nlriType.getIntValue(), nlriByteBuf, buffer);
235 public void serializeAttribute(final DataObject attribute, final ByteBuf byteAggregator) {
236 Preconditions.checkArgument(attribute instanceof PathAttributes, "Attribute parameter is not a PathAttribute object.");
237 final PathAttributes pathAttributes = (PathAttributes) attribute;
238 final PathAttributes1 pathAttributes1 = pathAttributes.getAugmentation(PathAttributes1.class);
239 final PathAttributes2 pathAttributes2 = pathAttributes.getAugmentation(PathAttributes2.class);
240 if (pathAttributes1 != null) {
241 final AdvertizedRoutes routes = (pathAttributes1.getMpReachNlri()).getAdvertizedRoutes();
242 if (routes != null &&
243 routes.getDestinationType()
245 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) {
246 final 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
247 linkstateCase = (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) routes.getDestinationType();
249 for (final CLinkstateDestination cLinkstateDestination : linkstateCase.getDestinationLinkstate().getCLinkstateDestination()) {
250 serializeNlri(cLinkstateDestination, byteAggregator);
253 } else if (pathAttributes2 != null) {
254 final MpUnreachNlri mpUnreachNlri = pathAttributes2.getMpUnreachNlri();
255 if (mpUnreachNlri.getWithdrawnRoutes() != null && mpUnreachNlri.getWithdrawnRoutes().getDestinationType() instanceof DestinationLinkstateCase) {
256 final DestinationLinkstateCase linkstateCase = (DestinationLinkstateCase) mpUnreachNlri.getWithdrawnRoutes().getDestinationType();
257 for (final CLinkstateDestination cLinkstateDestination : linkstateCase.getDestinationLinkstate().getCLinkstateDestination()) {
258 serializeNlri(cLinkstateDestination, byteAggregator);