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 io.netty.buffer.ByteBuf;
12 import java.util.ArrayList;
13 import java.util.List;
14 import org.opendaylight.bgp.concepts.RouteDistinguisherUtil;
15 import org.opendaylight.protocol.bgp.linkstate.spi.AbstractTeLspNlriCodec;
16 import org.opendaylight.protocol.bgp.linkstate.spi.pojo.SimpleNlriTypeRegistry;
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.protocol.bgp.parser.spi.PeerSpecificParserConstraint;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.Identifier;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.ProtocolId;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.ObjectType;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.destination.CLinkstateDestination;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.destination.CLinkstateDestinationBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.LinkCaseBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.NodeCaseBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.PrefixCaseBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.link._case.LinkDescriptors;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.link._case.LocalNodeDescriptors;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.link._case.RemoteNodeDescriptors;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.node._case.NodeDescriptors;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.prefix._case.AdvertisingNodeDescriptors;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.linkstate.object.type.prefix._case.PrefixDescriptors;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCaseBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.linkstate._case.DestinationLinkstateBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationLinkstateCase;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev200120.path.attributes.Attributes;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.AttributesReach;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.AttributesUnreach;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.attributes.reach.MpReachNlriBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.attributes.reach.mp.reach.nlri.AdvertizedRoutes;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.attributes.reach.mp.reach.nlri.AdvertizedRoutesBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.attributes.unreach.MpUnreachNlriBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.attributes.unreach.mp.unreach.nlri.WithdrawnRoutes;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev180329.attributes.unreach.mp.unreach.nlri.WithdrawnRoutesBuilder;
47 import org.opendaylight.yangtools.yang.common.QName;
48 import org.opendaylight.yangtools.yang.common.Uint64;
49 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
50 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
51 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
52 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
57 * Parser and serializer for Linkstate NLRI.
59 public final class LinkstateNlriParser implements NlriParser, NlriSerializer {
60 private static final Logger LOG = LoggerFactory.getLogger(LinkstateNlriParser.class);
63 public static final NodeIdentifier OBJECT_TYPE_NID = NodeIdentifier.create(ObjectType.QNAME);
65 public static final NodeIdentifier NODE_DESCRIPTORS_NID = NodeIdentifier.create(NodeDescriptors.QNAME);
67 public static final NodeIdentifier LOCAL_NODE_DESCRIPTORS_NID = NodeIdentifier.create(LocalNodeDescriptors.QNAME);
69 public static final NodeIdentifier REMOTE_NODE_DESCRIPTORS_NID = NodeIdentifier.create(RemoteNodeDescriptors.QNAME);
71 public static final NodeIdentifier ADVERTISING_NODE_DESCRIPTORS_NID = NodeIdentifier.create(
72 AdvertisingNodeDescriptors.QNAME);
74 public static final NodeIdentifier PREFIX_DESCRIPTORS_NID = NodeIdentifier.create(PrefixDescriptors.QNAME);
76 public static final NodeIdentifier LINK_DESCRIPTORS_NID = NodeIdentifier.create(LinkDescriptors.QNAME);
78 public static final NodeIdentifier PROTOCOL_ID_NID = NodeIdentifier.create(
79 QName.create(CLinkstateDestination.QNAME.getModule(), "protocol-id").intern());
81 public static final NodeIdentifier IDENTIFIER_NID = NodeIdentifier.create(
82 QName.create(CLinkstateDestination.QNAME.getModule(), "identifier").intern());
84 private static final NodeIdentifier DISTINGUISHER_NID = NodeIdentifier.create(
85 QName.create(CLinkstateDestination.QNAME.getModule(), "route-distinguisher").intern());
86 private final SimpleNlriTypeRegistry nlriTypeReg = SimpleNlriTypeRegistry.getInstance();
90 * Parses common parts for Link State Nodes, Links and Prefixes, that includes protocol ID and identifier tlv.
92 * @param nlri as byte array
93 * @return {@link CLinkstateDestination}
95 private List<CLinkstateDestination> parseNlri(final ByteBuf nlri) {
96 final List<CLinkstateDestination> dests = new ArrayList<>();
97 while (nlri.isReadable()) {
98 final CLinkstateDestination destination = nlriTypeReg.parseNlriType(nlri);
99 if (destination == null) {
102 dests.add(destination);
108 public void parseNlri(final ByteBuf nlri, final MpUnreachNlriBuilder builder,
109 final PeerSpecificParserConstraint constraint) throws BGPParsingException {
110 if (!nlri.isReadable()) {
113 final List<CLinkstateDestination> dst = parseNlri(nlri);
115 builder.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(
116 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.update
117 .attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationLinkstateCaseBuilder()
118 .setDestinationLinkstate(new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang
119 .bgp.linkstate.rev200120.update.attributes.mp.unreach.nlri.withdrawn.routes.destination
120 .type.destination.linkstate._case.DestinationLinkstateBuilder()
121 .setCLinkstateDestination(dst).build()).build()).build());
125 public void parseNlri(final ByteBuf nlri, final MpReachNlriBuilder builder,
126 final PeerSpecificParserConstraint constraint) throws BGPParsingException {
127 if (!nlri.isReadable()) {
130 final List<CLinkstateDestination> dst = parseNlri(nlri);
132 builder.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(
133 new DestinationLinkstateCaseBuilder().setDestinationLinkstate(
134 new DestinationLinkstateBuilder().setCLinkstateDestination(dst).build()).build()).build());
138 public void serializeAttribute(final Attributes pathAttributes, final ByteBuf byteAggregator) {
139 final AttributesReach pathAttributes1 = pathAttributes.augmentation(AttributesReach.class);
140 final AttributesUnreach pathAttributes2 = pathAttributes.augmentation(AttributesUnreach.class);
141 if (pathAttributes1 != null) {
142 serializeAdvertisedRoutes(pathAttributes1.getMpReachNlri().getAdvertizedRoutes(), byteAggregator);
143 } else if (pathAttributes2 != null) {
144 serializeWithDrawnRoutes(pathAttributes2.getMpUnreachNlri().getWithdrawnRoutes(), byteAggregator);
148 private void serializeWithDrawnRoutes(final WithdrawnRoutes withdrawnRoutes, final ByteBuf byteAggregator) {
149 if (withdrawnRoutes != null && withdrawnRoutes.getDestinationType() instanceof DestinationLinkstateCase) {
150 final DestinationLinkstateCase linkstateCase
151 = (DestinationLinkstateCase) withdrawnRoutes.getDestinationType();
152 for (final CLinkstateDestination linkstateDestinationCase : linkstateCase.getDestinationLinkstate()
153 .getCLinkstateDestination()) {
154 nlriTypeReg.serializeNlriType(linkstateDestinationCase, byteAggregator);
159 private void serializeAdvertisedRoutes(final AdvertizedRoutes advertizedRoutes, final ByteBuf byteAggregator) {
160 if (advertizedRoutes != null && advertizedRoutes.getDestinationType()
162 org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.update
163 .attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase) {
164 final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev200120.update
165 .attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase
166 linkstateCase = (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang
167 .bgp.linkstate.rev200120.update.attributes.mp.reach.nlri.advertized.routes.destination.type
168 .DestinationLinkstateCase) advertizedRoutes.getDestinationType();
170 for (var linkstateDestinationCase : linkstateCase.getDestinationLinkstate().getCLinkstateDestination()) {
171 nlriTypeReg.serializeNlriType(linkstateDestinationCase, byteAggregator);
177 private static int domProtocolIdValue(final String protocolId) {
178 return switch (protocolId) {
179 case "isis-level1" -> ProtocolId.IsisLevel1.getIntValue();
180 case "isis-level2" -> ProtocolId.IsisLevel2.getIntValue();
181 case "ospf" -> ProtocolId.Ospf.getIntValue();
182 case "direct" -> ProtocolId.Direct.getIntValue();
183 case "static" -> ProtocolId.Static.getIntValue();
184 case "ospf-v3" -> ProtocolId.OspfV3.getIntValue();
185 case "rsvp-te" -> ProtocolId.RsvpTe.getIntValue();
186 case "bgp-epe" -> ProtocolId.BgpEpe.getIntValue();
187 case "segment-routing" -> ProtocolId.SegmentRouting.getIntValue();
192 public static CLinkstateDestination extractLinkstateDestination(final DataContainerNode linkstate) {
193 final var builder = new CLinkstateDestinationBuilder()
194 .setRouteDistinguisher(RouteDistinguisherUtil.extractRouteDistinguisher(linkstate, DISTINGUISHER_NID));
195 final var protocolId = linkstate.childByArg(PROTOCOL_ID_NID);
196 if (protocolId != null) {
197 // DOM representation contains values as are in the model, not as are in generated enum
198 builder.setProtocolId(ProtocolId.forValue(domProtocolIdValue((String) protocolId.body())));
200 final var identifier = linkstate.childByArg(IDENTIFIER_NID);
201 if (identifier != null) {
202 builder.setIdentifier(new Identifier((Uint64) identifier.body()));
206 .setObjectType(serializeObjectType((ChoiceNode) linkstate.getChildByArg(OBJECT_TYPE_NID)))
210 private static ObjectType serializeObjectType(final ChoiceNode objectType) {
211 final var advNode = objectType.childByArg(ADVERTISING_NODE_DESCRIPTORS_NID);
212 if (advNode != null) {
213 // prefix node descriptors
214 final var builder = new PrefixCaseBuilder()
215 .setAdvertisingNodeDescriptors(NodeNlriParser.serializeAdvNodeDescriptors((ContainerNode) advNode));
217 // prefix descriptors
218 final var prefix = objectType.childByArg(PREFIX_DESCRIPTORS_NID);
219 if (prefix != null) {
220 builder.setPrefixDescriptors(
221 AbstractPrefixNlriParser.serializePrefixDescriptors((ContainerNode) prefix));
223 return builder.build();
226 final var localNode = objectType.childByArg(LOCAL_NODE_DESCRIPTORS_NID);
227 if (localNode != null) {
228 // link local node descriptors
229 final var builder = new LinkCaseBuilder()
230 .setLocalNodeDescriptors(NodeNlriParser.serializeLocalNodeDescriptors((ContainerNode) localNode));
231 // link remote node descriptors
232 final var remoteNode = objectType.childByArg(REMOTE_NODE_DESCRIPTORS_NID);
233 if (remoteNode != null) {
234 builder.setRemoteNodeDescriptors(
235 NodeNlriParser.serializeRemoteNodeDescriptors((ContainerNode) remoteNode));
238 final var link = objectType.childByArg(LINK_DESCRIPTORS_NID);
240 builder.setLinkDescriptors(LinkNlriParser.serializeLinkDescriptors((ContainerNode) link));
242 return builder.build();
245 final var node = objectType.childByArg(NODE_DESCRIPTORS_NID);
248 return new NodeCaseBuilder()
249 .setNodeDescriptors(NodeNlriParser.serializeNodeDescriptors((ContainerNode) node))
253 final var teLsp = AbstractTeLspNlriCodec.serializeObjectType(objectType);
258 LOG.warn("Ignoring unknown Object Type: {}.", objectType);