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.impl.nlri;
10 import com.google.common.annotations.VisibleForTesting;
11 import com.google.common.base.Preconditions;
12 import io.netty.buffer.ByteBuf;
13 import java.math.BigInteger;
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.Optional;
17 import org.opendaylight.bgp.concepts.RouteDistinguisherUtil;
18 import org.opendaylight.protocol.bgp.linkstate.spi.AbstractTeLspNlriCodec;
19 import org.opendaylight.protocol.bgp.linkstate.spi.pojo.SimpleNlriTypeRegistry;
20 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
21 import org.opendaylight.protocol.bgp.parser.spi.NlriParser;
22 import org.opendaylight.protocol.bgp.parser.spi.NlriSerializer;
23 import org.opendaylight.protocol.bgp.parser.spi.PeerSpecificParserConstraint;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.Identifier;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.ProtocolId;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.ObjectType;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.destination.CLinkstateDestination;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.destination.CLinkstateDestinationBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.object.type.LinkCaseBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.object.type.NodeCaseBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.object.type.PrefixCaseBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.object.type.link._case.LinkDescriptors;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.object.type.link._case.LocalNodeDescriptors;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.object.type.link._case.RemoteNodeDescriptors;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.object.type.node._case.NodeDescriptors;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.object.type.prefix._case.AdvertisingNodeDescriptors;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.linkstate.object.type.prefix._case.PrefixDescriptors;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCaseBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.update.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.rev180329.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationLinkstateCase;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.Attributes;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.Attributes1;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.Attributes2;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.MpReachNlriBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.MpUnreachNlriBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.reach.nlri.AdvertizedRoutes;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.unreach.nlri.WithdrawnRoutes;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.update.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
50 import org.opendaylight.yangtools.yang.binding.DataObject;
51 import org.opendaylight.yangtools.yang.common.QName;
52 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
53 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
54 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
55 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
56 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
57 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
62 * Parser and serializer for Linkstate NLRI.
64 public final class LinkstateNlriParser implements NlriParser, NlriSerializer {
65 private static final Logger LOG = LoggerFactory.getLogger(LinkstateNlriParser.class);
68 public static final NodeIdentifier OBJECT_TYPE_NID = new NodeIdentifier(ObjectType.QNAME);
70 public static final NodeIdentifier NODE_DESCRIPTORS_NID = new NodeIdentifier(NodeDescriptors.QNAME);
72 public static final NodeIdentifier LOCAL_NODE_DESCRIPTORS_NID = new NodeIdentifier(LocalNodeDescriptors.QNAME);
74 public static final NodeIdentifier REMOTE_NODE_DESCRIPTORS_NID = new NodeIdentifier(RemoteNodeDescriptors.QNAME);
76 public static final NodeIdentifier ADVERTISING_NODE_DESCRIPTORS_NID
77 = new NodeIdentifier(AdvertisingNodeDescriptors.QNAME);
79 public static final NodeIdentifier PREFIX_DESCRIPTORS_NID = new NodeIdentifier(PrefixDescriptors.QNAME);
81 public static final NodeIdentifier LINK_DESCRIPTORS_NID = new NodeIdentifier(LinkDescriptors.QNAME);
83 public static final NodeIdentifier PROTOCOL_ID_NID = new NodeIdentifier(
84 QName.create(CLinkstateDestination.QNAME.getModule(), "protocol-id"));
86 public static final NodeIdentifier IDENTIFIER_NID = new NodeIdentifier(
87 QName.create(CLinkstateDestination.QNAME.getModule(), "identifier"));
89 private static final NodeIdentifier DISTINGUISHER_NID = new NodeIdentifier(
90 QName.create(CLinkstateDestination.QNAME.getModule(), "route-distinguisher"));
91 private final SimpleNlriTypeRegistry nlriTypeReg = SimpleNlriTypeRegistry.getInstance();
95 * Parses common parts for Link State Nodes, Links and Prefixes, that includes protocol ID and identifier tlv.
97 * @param nlri as byte array
98 * @return {@link CLinkstateDestination}
100 private List<CLinkstateDestination> parseNlri(final ByteBuf nlri) {
101 final List<CLinkstateDestination> dests = new ArrayList<>();
102 while (nlri.isReadable()) {
103 final CLinkstateDestination destination = this.nlriTypeReg.parseNlriType(nlri);
104 if (destination == null) {
107 dests.add(destination);
113 public void parseNlri(final ByteBuf nlri, final MpUnreachNlriBuilder builder,
114 final PeerSpecificParserConstraint constraint) throws BGPParsingException {
115 if (!nlri.isReadable()) {
118 final List<CLinkstateDestination> dst = parseNlri(nlri);
120 builder.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(
121 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.update
122 .attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationLinkstateCaseBuilder()
123 .setDestinationLinkstate(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang
124 .bgp.linkstate.rev180329.update.attributes.mp.unreach.nlri.withdrawn.routes.destination
125 .type.destination.linkstate._case.DestinationLinkstateBuilder()
126 .setCLinkstateDestination(dst).build()).build()).build());
130 public void parseNlri(final ByteBuf nlri, final MpReachNlriBuilder builder,
131 final PeerSpecificParserConstraint constraint) throws BGPParsingException {
132 if (!nlri.isReadable()) {
135 final List<CLinkstateDestination> dst = parseNlri(nlri);
137 builder.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(
138 new DestinationLinkstateCaseBuilder().setDestinationLinkstate(
139 new DestinationLinkstateBuilder().setCLinkstateDestination(dst).build()).build()).build());
143 public void serializeAttribute(final DataObject attribute, final ByteBuf byteAggregator) {
144 Preconditions.checkArgument(attribute instanceof Attributes,
145 "Attribute parameter is not a PathAttribute object.");
146 final Attributes pathAttributes = (Attributes) attribute;
147 final Attributes1 pathAttributes1 = pathAttributes.getAugmentation(Attributes1.class);
148 final Attributes2 pathAttributes2 = pathAttributes.getAugmentation(Attributes2.class);
149 if (pathAttributes1 != null) {
150 serializeAdvertisedRoutes(pathAttributes1.getMpReachNlri().getAdvertizedRoutes(), byteAggregator);
151 } else if (pathAttributes2 != null) {
152 serializeWithDrawnRoutes(pathAttributes2.getMpUnreachNlri().getWithdrawnRoutes(), byteAggregator);
156 private void serializeWithDrawnRoutes(final WithdrawnRoutes withdrawnRoutes, final ByteBuf byteAggregator) {
157 if (withdrawnRoutes != null && withdrawnRoutes.getDestinationType() instanceof DestinationLinkstateCase) {
158 final DestinationLinkstateCase linkstateCase
159 = (DestinationLinkstateCase) withdrawnRoutes.getDestinationType();
160 for (final CLinkstateDestination cLinkstateDestination : linkstateCase.getDestinationLinkstate()
161 .getCLinkstateDestination()) {
162 this.nlriTypeReg.serializeNlriType(cLinkstateDestination, byteAggregator);
167 private void serializeAdvertisedRoutes(final AdvertizedRoutes advertizedRoutes, final ByteBuf byteAggregator) {
168 if (advertizedRoutes != null && advertizedRoutes.getDestinationType()
170 org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.update
171 .attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase) {
172 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev180329.update
173 .attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase
174 linkstateCase = (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate
175 .rev180329.update.attributes.mp.reach.nlri.advertized.routes.destination.type
176 .DestinationLinkstateCase) advertizedRoutes.getDestinationType();
178 for (final CLinkstateDestination cLinkstateDestination : linkstateCase.getDestinationLinkstate()
179 .getCLinkstateDestination()) {
180 this.nlriTypeReg.serializeNlriType(cLinkstateDestination, byteAggregator);
186 private static int domProtocolIdValue(final String protocolId) {
187 switch (protocolId) {
189 return ProtocolId.IsisLevel1.getIntValue();
191 return ProtocolId.IsisLevel2.getIntValue();
193 return ProtocolId.Ospf.getIntValue();
195 return ProtocolId.Direct.getIntValue();
197 return ProtocolId.Static.getIntValue();
199 return ProtocolId.OspfV3.getIntValue();
201 return ProtocolId.RsvpTe.getIntValue();
203 return ProtocolId.BgpEpe.getIntValue();
204 case "segment-routing":
205 return ProtocolId.SegmentRouting.getIntValue();
211 public static CLinkstateDestination extractLinkstateDestination(
212 final DataContainerNode<? extends PathArgument> linkstate) {
213 final CLinkstateDestinationBuilder builder = new CLinkstateDestinationBuilder();
214 serializeCommonParts(builder, linkstate);
216 final ChoiceNode objectType = (ChoiceNode) linkstate.getChild(OBJECT_TYPE_NID).get();
217 if (objectType.getChild(ADVERTISING_NODE_DESCRIPTORS_NID).isPresent()) {
218 serializeAdvertisedNodeDescriptor(builder, objectType);
219 } else if (objectType.getChild(LOCAL_NODE_DESCRIPTORS_NID).isPresent()) {
220 serializeLocalNodeDescriptor(builder, objectType);
221 } else if (objectType.getChild(NODE_DESCRIPTORS_NID).isPresent()) {
222 serializeNodeDescriptor(builder, objectType);
223 } else if (AbstractTeLspNlriCodec.isTeLsp(objectType)) {
224 builder.setObjectType(AbstractTeLspNlriCodec.serializeTeLsp(objectType));
226 LOG.warn("Unknown Object Type: {}.", objectType);
228 return builder.build();
231 private static void serializeNodeDescriptor(final CLinkstateDestinationBuilder builder,
232 final ChoiceNode objectType) {
233 final NodeCaseBuilder nodeBuilder = new NodeCaseBuilder();
235 nodeBuilder.setNodeDescriptors(NodeNlriParser
236 .serializeNodeDescriptors((ContainerNode) objectType.getChild(NODE_DESCRIPTORS_NID).get()));
237 builder.setObjectType(nodeBuilder.build());
240 private static void serializeLocalNodeDescriptor(final CLinkstateDestinationBuilder builder,
241 final ChoiceNode objectType) {
242 // link local node descriptors
243 final LinkCaseBuilder linkBuilder = new LinkCaseBuilder();
245 linkBuilder.setLocalNodeDescriptors(NodeNlriParser.serializeLocalNodeDescriptors((ContainerNode) objectType
246 .getChild(LOCAL_NODE_DESCRIPTORS_NID).get()));
247 // link remote node descriptors
248 if (objectType.getChild(REMOTE_NODE_DESCRIPTORS_NID).isPresent()) {
249 linkBuilder.setRemoteNodeDescriptors(NodeNlriParser
250 .serializeRemoteNodeDescriptors((ContainerNode) objectType.getChild(REMOTE_NODE_DESCRIPTORS_NID)
254 final Optional<DataContainerChild<? extends PathArgument, ?>> linkDescriptors
255 = objectType.getChild(LINK_DESCRIPTORS_NID);
256 linkDescriptors.ifPresent(dataContainerChild -> linkBuilder.setLinkDescriptors(LinkNlriParser
257 .serializeLinkDescriptors((ContainerNode) dataContainerChild)));
258 builder.setObjectType(linkBuilder.build());
261 private static void serializeAdvertisedNodeDescriptor(final CLinkstateDestinationBuilder builder,
262 final ChoiceNode objectType) {
263 // prefix node descriptors
264 final PrefixCaseBuilder prefixBuilder = new PrefixCaseBuilder();
265 prefixBuilder.setAdvertisingNodeDescriptors(NodeNlriParser
266 .serializeAdvNodeDescriptors((ContainerNode) objectType.getChild(ADVERTISING_NODE_DESCRIPTORS_NID)
269 // prefix descriptors
270 final Optional<DataContainerChild<? extends PathArgument, ?>> prefixDescriptors
271 = objectType.getChild(PREFIX_DESCRIPTORS_NID);
272 prefixDescriptors.ifPresent(dataContainerChild -> prefixBuilder.setPrefixDescriptors(AbstractPrefixNlriParser
273 .serializePrefixDescriptors((ContainerNode) dataContainerChild)));
274 builder.setObjectType(prefixBuilder.build());
277 private static void serializeCommonParts(final CLinkstateDestinationBuilder builder,
278 final DataContainerNode<? extends PathArgument> linkstate) {
279 // serialize common parts
280 final Optional<DataContainerChild<? extends PathArgument, ?>> distinguisher
281 = linkstate.getChild(DISTINGUISHER_NID);
282 distinguisher.ifPresent(dataContainerChild -> builder.setRouteDistinguisher(RouteDistinguisherUtil
283 .parseRouteDistinguisher(dataContainerChild.getValue())));
284 final Optional<DataContainerChild<? extends PathArgument, ?>> protocolId = linkstate.getChild(PROTOCOL_ID_NID);
285 // DOM representation contains values as are in the model, not as are in generated enum
286 protocolId.ifPresent(dataContainerChild -> builder.setProtocolId(ProtocolId
287 .forValue(domProtocolIdValue((String) dataContainerChild.getValue()))));
288 final Optional<DataContainerChild<? extends PathArgument, ?>> identifier = linkstate.getChild(IDENTIFIER_NID);
289 identifier.ifPresent(dataContainerChild -> builder
290 .setIdentifier(new Identifier((BigInteger) dataContainerChild.getValue())));