BUG-4692: Migrate TCP-MD5 support in bgp package to netty's native-epoll
[bgpcep.git] / bgp / linkstate / src / main / java / org / opendaylight / protocol / bgp / linkstate / impl / nlri / LinkstateNlriParser.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.impl.nlri;
9
10 import com.google.common.annotations.VisibleForTesting;
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import io.netty.buffer.ByteBuf;
14 import java.math.BigInteger;
15 import java.util.ArrayList;
16 import java.util.List;
17 import org.opendaylight.protocol.bgp.linkstate.spi.AbstractTeLspNlriCodec;
18 import org.opendaylight.protocol.bgp.linkstate.spi.pojo.SimpleNlriTypeRegistry;
19 import org.opendaylight.protocol.bgp.parser.BGPParsingException;
20 import org.opendaylight.protocol.bgp.parser.spi.NlriParser;
21 import org.opendaylight.protocol.bgp.parser.spi.NlriSerializer;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.Identifier;
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.LinkCaseBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.NodeCaseBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.PrefixCaseBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.link._case.LinkDescriptors;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.link._case.LocalNodeDescriptors;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.link._case.RemoteNodeDescriptors;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.node._case.NodeDescriptors;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.prefix._case.AdvertisingNodeDescriptors;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.linkstate.object.type.prefix._case.PrefixDescriptors;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCaseBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.linkstate._case.DestinationLinkstateBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationLinkstateCase;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev130919.path.attributes.Attributes;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes1;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.Attributes2;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlriBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlriBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.reach.nlri.AdvertizedRoutes;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.unreach.nlri.WithdrawnRoutes;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
49 import org.opendaylight.yangtools.yang.binding.DataObject;
50 import org.opendaylight.yangtools.yang.common.QName;
51 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
52 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
53 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
54 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
55 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
56 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
57 import org.slf4j.Logger;
58 import org.slf4j.LoggerFactory;
59
60 /**
61  * Parser and serializer for Linkstate NLRI.
62  */
63 public final class LinkstateNlriParser implements NlriParser, NlriSerializer {
64
65     @VisibleForTesting
66     public static final NodeIdentifier OBJECT_TYPE_NID = new NodeIdentifier(ObjectType.QNAME);
67     @VisibleForTesting
68     public static final NodeIdentifier NODE_DESCRIPTORS_NID = new NodeIdentifier(NodeDescriptors.QNAME);
69     @VisibleForTesting
70     public static final NodeIdentifier LOCAL_NODE_DESCRIPTORS_NID = new NodeIdentifier(LocalNodeDescriptors.QNAME);
71     @VisibleForTesting
72     public static final NodeIdentifier REMOTE_NODE_DESCRIPTORS_NID = new NodeIdentifier(RemoteNodeDescriptors.QNAME);
73     @VisibleForTesting
74     public static final NodeIdentifier ADVERTISING_NODE_DESCRIPTORS_NID = new NodeIdentifier(AdvertisingNodeDescriptors.QNAME);
75     @VisibleForTesting
76     public static final NodeIdentifier PREFIX_DESCRIPTORS_NID = new NodeIdentifier(PrefixDescriptors.QNAME);
77     @VisibleForTesting
78     public static final NodeIdentifier LINK_DESCRIPTORS_NID = new NodeIdentifier(LinkDescriptors.QNAME);
79     @VisibleForTesting
80     public static final NodeIdentifier PROTOCOL_ID_NID = new NodeIdentifier(QName.create(CLinkstateDestination.QNAME, "protocol-id").intern());
81     @VisibleForTesting
82     public static final NodeIdentifier IDENTIFIER_NID = new NodeIdentifier(QName.create(CLinkstateDestination.QNAME, "identifier").intern());
83     private static final Logger LOG = LoggerFactory.getLogger(LinkstateNlriParser.class);
84     @VisibleForTesting
85     private static final NodeIdentifier DISTINGUISHER_NID = new NodeIdentifier(QName.create(CLinkstateDestination.QNAME, "distinguisher").intern());
86     private final SimpleNlriTypeRegistry nlriTypeReg = SimpleNlriTypeRegistry.getInstance();
87
88
89     /**
90      * Parses common parts for Link State Nodes, Links and Prefixes, that includes protocol ID and identifier tlv.
91      *
92      * @param nlri as byte array
93      * @return {@link CLinkstateDestination}
94      */
95     private List<CLinkstateDestination> parseNlri(final ByteBuf nlri) {
96         final List<CLinkstateDestination> dests = new ArrayList<>();
97         while (nlri.isReadable()) {
98             final CLinkstateDestination destination = this.nlriTypeReg.parseNlriType(nlri);
99             if (destination == null) {
100                 continue;
101             }
102             dests.add(destination);
103         }
104         return dests;
105     }
106
107     @Override
108     public void parseNlri(final ByteBuf nlri, final MpUnreachNlriBuilder builder) throws BGPParsingException {
109         if (!nlri.isReadable()) {
110             return;
111         }
112         final List<CLinkstateDestination> dst = parseNlri(nlri);
113
114         builder.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(
115             new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationLinkstateCaseBuilder().setDestinationLinkstate(
116                 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.linkstate._case.DestinationLinkstateBuilder().setCLinkstateDestination(
117                     dst).build()).build()).build());
118     }
119
120     @Override
121     public void parseNlri(final ByteBuf nlri, final MpReachNlriBuilder builder) throws BGPParsingException {
122         if (!nlri.isReadable()) {
123             return;
124         }
125         final List<CLinkstateDestination> dst = parseNlri(nlri);
126
127         builder.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(
128             new DestinationLinkstateCaseBuilder().setDestinationLinkstate(
129                 new DestinationLinkstateBuilder().setCLinkstateDestination(dst).build()).build()).build());
130     }
131
132     @Override
133     public void serializeAttribute(final DataObject attribute, final ByteBuf byteAggregator) {
134         Preconditions.checkArgument(attribute instanceof Attributes, "Attribute parameter is not a PathAttribute object.");
135         final Attributes pathAttributes = (Attributes) attribute;
136         final Attributes1 pathAttributes1 = pathAttributes.getAugmentation(Attributes1.class);
137         final Attributes2 pathAttributes2 = pathAttributes.getAugmentation(Attributes2.class);
138         if (pathAttributes1 != null) {
139             serializeAdvertisedRoutes((pathAttributes1.getMpReachNlri()).getAdvertizedRoutes(), byteAggregator);
140         } else if (pathAttributes2 != null) {
141             serializeWithDrawnRoutes(pathAttributes2.getMpUnreachNlri().getWithdrawnRoutes(), byteAggregator);
142         }
143     }
144
145     private void serializeWithDrawnRoutes(final WithdrawnRoutes withdrawnRoutes, final ByteBuf byteAggregator) {
146         if (withdrawnRoutes != null && withdrawnRoutes.getDestinationType() instanceof DestinationLinkstateCase) {
147             final DestinationLinkstateCase linkstateCase = (DestinationLinkstateCase) withdrawnRoutes.getDestinationType();
148             for (final CLinkstateDestination cLinkstateDestination : linkstateCase.getDestinationLinkstate().getCLinkstateDestination()) {
149                 this.nlriTypeReg.serializeNlriType(cLinkstateDestination, byteAggregator);
150             }
151         }
152     }
153
154     private void serializeAdvertisedRoutes(final AdvertizedRoutes advertizedRoutes, final ByteBuf byteAggregator) {
155         if (advertizedRoutes != null && advertizedRoutes.getDestinationType()
156             instanceof
157             org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase) {
158             final org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase
159                 linkstateCase = (org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.linkstate.rev150210.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationLinkstateCase) advertizedRoutes.getDestinationType();
160
161             for (final CLinkstateDestination cLinkstateDestination : linkstateCase.getDestinationLinkstate().getCLinkstateDestination()) {
162                 this.nlriTypeReg.serializeNlriType(cLinkstateDestination, byteAggregator);
163             }
164         }
165     }
166
167     // FIXME : use codec
168     private static int domProtocolIdValue(final String protocolId) {
169         switch (protocolId) {
170         case "isis-level1":
171             return ProtocolId.IsisLevel1.getIntValue();
172         case "isis-level2":
173             return ProtocolId.IsisLevel2.getIntValue();
174         case "ospf":
175             return ProtocolId.Ospf.getIntValue();
176         case "direct":
177             return ProtocolId.Direct.getIntValue();
178         case "static":
179             return ProtocolId.Static.getIntValue();
180         case "ospf-v3":
181             return ProtocolId.OspfV3.getIntValue();
182         case "rsvp-te":
183             return ProtocolId.RsvpTe.getIntValue();
184         case "bgp-epe":
185             return ProtocolId.BgpEpe.getIntValue();
186         case "segment-routing":
187             return ProtocolId.SegmentRouting.getIntValue();
188         default:
189             return 0;
190         }
191     }
192
193     public static CLinkstateDestination extractLinkstateDestination(final DataContainerNode<? extends PathArgument> linkstate) {
194         final CLinkstateDestinationBuilder builder = new CLinkstateDestinationBuilder();
195         serializeCommonParts(builder, linkstate);
196
197         final ChoiceNode objectType = (ChoiceNode) linkstate.getChild(OBJECT_TYPE_NID).get();
198         if (objectType.getChild(ADVERTISING_NODE_DESCRIPTORS_NID).isPresent()) {
199             serializeAdvertisedNodeDescriptor(builder, objectType);
200         } else if (objectType.getChild(LOCAL_NODE_DESCRIPTORS_NID).isPresent()) {
201             serializeLocalNodeDescriptor(builder, objectType);
202         } else if (objectType.getChild(NODE_DESCRIPTORS_NID).isPresent()) {
203             serializeNodeDescriptor(builder, objectType);
204         } else if (AbstractTeLspNlriCodec.isTeLsp(objectType)) {
205             builder.setObjectType(AbstractTeLspNlriCodec.serializeTeLsp(objectType));
206         } else {
207             LOG.warn("Unknown Object Type: {}.", objectType);
208         }
209         return builder.build();
210     }
211
212     private static void serializeNodeDescriptor(final CLinkstateDestinationBuilder builder, final ChoiceNode objectType) {
213         final NodeCaseBuilder nodeBuilder = new NodeCaseBuilder();
214         // node descriptors
215         nodeBuilder.setNodeDescriptors(NodeNlriParser.serializeNodeDescriptors((ContainerNode) objectType.getChild(NODE_DESCRIPTORS_NID).get()));
216         builder.setObjectType(nodeBuilder.build());
217     }
218
219     private static void serializeLocalNodeDescriptor(final CLinkstateDestinationBuilder builder, final ChoiceNode objectType) {
220         // link local node descriptors
221         final LinkCaseBuilder linkBuilder = new LinkCaseBuilder();
222
223         linkBuilder.setLocalNodeDescriptors(NodeNlriParser.serializeLocalNodeDescriptors((ContainerNode) objectType.getChild(LOCAL_NODE_DESCRIPTORS_NID).get()));
224         // link remote node descriptors
225         if (objectType.getChild(REMOTE_NODE_DESCRIPTORS_NID).isPresent()) {
226             linkBuilder.setRemoteNodeDescriptors(NodeNlriParser.serializeRemoteNodeDescriptors((ContainerNode) objectType.getChild(REMOTE_NODE_DESCRIPTORS_NID).get()));
227         }
228         // link descriptors
229         final Optional<DataContainerChild<? extends PathArgument, ?>> linkDescriptors = objectType.getChild(LINK_DESCRIPTORS_NID);
230         if (linkDescriptors.isPresent()) {
231             linkBuilder.setLinkDescriptors(LinkNlriParser.serializeLinkDescriptors((ContainerNode) linkDescriptors.get()));
232         }
233         builder.setObjectType(linkBuilder.build());
234     }
235
236     private static void serializeAdvertisedNodeDescriptor(final CLinkstateDestinationBuilder builder, final ChoiceNode objectType) {
237         // prefix node descriptors
238         final PrefixCaseBuilder prefixBuilder = new PrefixCaseBuilder();
239         prefixBuilder.setAdvertisingNodeDescriptors(NodeNlriParser.serializeAdvNodeDescriptors((ContainerNode) objectType.getChild(
240             ADVERTISING_NODE_DESCRIPTORS_NID).get()));
241
242         // prefix descriptors
243         final Optional<DataContainerChild<? extends PathArgument, ?>> prefixDescriptors = objectType.getChild(PREFIX_DESCRIPTORS_NID);
244         if (prefixDescriptors.isPresent()) {
245             prefixBuilder.setPrefixDescriptors(AbstractPrefixNlriParser.serializePrefixDescriptors((ContainerNode) prefixDescriptors.get()));
246         }
247         builder.setObjectType(prefixBuilder.build());
248     }
249
250     private static void serializeCommonParts(final CLinkstateDestinationBuilder builder, final DataContainerNode<? extends PathArgument> linkstate) {
251         // serialize common parts
252         final Optional<DataContainerChild<? extends PathArgument, ?>> distinguisher = linkstate.getChild(DISTINGUISHER_NID);
253         if (distinguisher.isPresent()) {
254             builder.setDistinguisher(new RouteDistinguisher((BigInteger) distinguisher.get().getValue()));
255         }
256         final Optional<DataContainerChild<? extends PathArgument, ?>> protocolId = linkstate.getChild(PROTOCOL_ID_NID);
257         // DOM representation contains values as are in the model, not as are in generated enum
258         if (protocolId.isPresent()) {
259             builder.setProtocolId(ProtocolId.forValue(domProtocolIdValue((String) protocolId.get().getValue())));
260         }
261         final Optional<DataContainerChild<? extends PathArgument, ?>> identifier = linkstate.getChild(IDENTIFIER_NID);
262         if (identifier.isPresent()) {
263             builder.setIdentifier(new Identifier((BigInteger) identifier.get().getValue()));
264         }
265     }
266 }