Migrate to MD-SAL APIs
[bgpcep.git] / bgp / extensions / labeled-unicast / src / main / java / org / opendaylight / protocol / bgp / labeled / unicast / AbstractLabeledUnicastRIBSupport.java
1 /*
2  * Copyright (c) 2016 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.labeled.unicast;
9
10 import io.netty.buffer.ByteBuf;
11 import io.netty.buffer.Unpooled;
12 import java.util.ArrayList;
13 import java.util.Collection;
14 import java.util.Collections;
15 import java.util.List;
16 import java.util.Optional;
17 import java.util.stream.Collectors;
18 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
19 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
20 import org.opendaylight.protocol.bgp.parser.spi.PathIdUtil;
21 import org.opendaylight.protocol.bgp.rib.spi.AbstractRIBSupport;
22 import org.opendaylight.protocol.util.ByteArray;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.labeled.unicast.rev180329.LabeledUnicastRoutesList;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.labeled.unicast.rev180329.LabeledUnicastSubsequentAddressFamily;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.labeled.unicast.rev180329.labeled.unicast.LabelStack;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.labeled.unicast.rev180329.labeled.unicast.LabelStackBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.labeled.unicast.rev180329.labeled.unicast.destination.CLabeledUnicastDestination;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.labeled.unicast.rev180329.labeled.unicast.destination.CLabeledUnicastDestinationBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.labeled.unicast.rev180329.labeled.unicast.routes.list.LabeledUnicastRoute;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.labeled.unicast.rev180329.labeled.unicast.routes.list.LabeledUnicastRouteBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.labeled.unicast.rev180329.labeled.unicast.routes.list.LabeledUnicastRouteKey;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.PathId;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.Attributes;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev180329.rib.tables.Routes;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.AddressFamily;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel;
38 import org.opendaylight.yangtools.yang.binding.ChildOf;
39 import org.opendaylight.yangtools.yang.binding.DataObject;
40 import org.opendaylight.yangtools.yang.common.QName;
41 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
42 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
43 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
44 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
45 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
46 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
47 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
48 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
49 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
50 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 abstract class AbstractLabeledUnicastRIBSupport<
55         C extends Routes & DataObject,
56         S extends ChildOf<? super C> & LabeledUnicastRoutesList>
57         extends AbstractRIBSupport<C, S, LabeledUnicastRoute, LabeledUnicastRouteKey> {
58     private static final NodeIdentifier LABEL_STACK_NID
59             = NodeIdentifier.create(QName.create(CLabeledUnicastDestination.QNAME, "label-stack").intern());
60     private static final NodeIdentifier LV_NID
61             = NodeIdentifier.create(QName.create(CLabeledUnicastDestination.QNAME, "label-value").intern());
62     private static final NodeIdentifier NLRI_ROUTES_LIST = NodeIdentifier.create(CLabeledUnicastDestination.QNAME);
63     private static final Logger LOG = LoggerFactory.getLogger(AbstractLabeledUnicastRIBSupport.class);
64
65     /**
66      * Default constructor. Requires the QName of the container augmented under the routes choice
67      * node in instantiations of the rib grouping. It is assumed that this container is defined by
68      * the same model which populates it with route grouping instantiation, and by extension with
69      * the route attributes container.
70      * @param mappingService  Binding Normalized Node Serializer
71      * @param cazeClass Binding class of the AFI/SAFI-specific case statement, must not be null
72      * @param containerClass Binding class of the container in routes choice, must not be null.
73      * @param addressFamilyClass address Family Class
74      * @param destinationQname destination Qname
75      */
76     AbstractLabeledUnicastRIBSupport(
77             final BindingNormalizedNodeSerializer mappingService,
78             final Class<C> cazeClass,
79             final Class<S> containerClass,
80             final Class<? extends AddressFamily> addressFamilyClass,
81             final QName destinationQname) {
82         super(mappingService,
83                 cazeClass,
84                 containerClass,
85                 LabeledUnicastRoute.class,
86                 addressFamilyClass,
87                 LabeledUnicastSubsequentAddressFamily.class,
88                 destinationQname);
89     }
90
91     @Override
92     protected Collection<NodeIdentifierWithPredicates> processDestination(final DOMDataTreeWriteTransaction tx,
93                                                                           final YangInstanceIdentifier routesPath,
94                                                                           final ContainerNode destination,
95                                                                           final ContainerNode attributes,
96                                                                           final ApplyRoute function) {
97         if (destination != null) {
98             final Optional<DataContainerChild<? extends PathArgument, ?>> maybeRoutes
99                     = destination.getChild(NLRI_ROUTES_LIST);
100             if (maybeRoutes.isPresent()) {
101                 final DataContainerChild<? extends PathArgument, ?> routes = maybeRoutes.get();
102                 if (routes instanceof UnkeyedListNode) {
103                     final YangInstanceIdentifier base = routesYangInstanceIdentifier(routesPath);
104                     final Collection<UnkeyedListEntryNode> routesList = ((UnkeyedListNode) routes).getValue();
105                     final List<NodeIdentifierWithPredicates> keys = new ArrayList<>(routesList.size());
106                     for (final UnkeyedListEntryNode labeledUcastDest : routesList) {
107                         final NodeIdentifierWithPredicates routeKey = createRouteKey(labeledUcastDest);
108                         function.apply(tx, base, routeKey, labeledUcastDest, attributes);
109                         keys.add(routeKey);
110                     }
111                     return keys;
112                 } else {
113                     LOG.warn("Routes {} are not a map", routes);
114                 }
115             }
116         }
117         return Collections.emptyList();
118     }
119
120
121     protected List<CLabeledUnicastDestination> extractRoutes(final Collection<MapEntryNode> routes) {
122         return routes.stream().map(this::extractCLabeledUnicastDestination).collect(Collectors.toList());
123     }
124
125     private NodeIdentifierWithPredicates createRouteKey(final UnkeyedListEntryNode labeledUnicast) {
126         final ByteBuf buffer = Unpooled.buffer();
127
128         final CLabeledUnicastDestination dest = extractCLabeledUnicastDestination(labeledUnicast);
129         LUNlriParser.serializeNlri(Collections.singletonList(dest), false, buffer);
130         final String routeKeyValue = ByteArray.encodeBase64(buffer);
131         final Optional<DataContainerChild<? extends PathArgument, ?>> maybePathIdLeaf
132                 = labeledUnicast.getChild(routePathIdNid());
133         return PathIdUtil.createNidKey(routeQName(), routeKeyQName(), pathIdQName(), routeKeyValue, maybePathIdLeaf);
134     }
135
136     /**
137      * Conversion from DataContainer to LabeledUnicastDestination Object.
138      *
139      * @param route DataContainer
140      * @return LabeledUnicastDestination Object
141      */
142     private CLabeledUnicastDestination extractCLabeledUnicastDestination(
143             final DataContainerNode<? extends PathArgument> route) {
144         final CLabeledUnicastDestinationBuilder builder = new CLabeledUnicastDestinationBuilder();
145         builder.setPrefix(extractPrefix(route, prefixNid()));
146         builder.setLabelStack(extractLabel(route, LABEL_STACK_NID, LV_NID));
147         builder.setPathId(PathIdUtil.buildPathId(route, routePathIdNid()));
148         return builder.build();
149     }
150
151     protected abstract IpPrefix extractPrefix(DataContainerNode<? extends PathArgument> route,
152             NodeIdentifier prefixTypeNid);
153
154     public static List<LabelStack> extractLabel(final DataContainerNode<? extends PathArgument> route,
155             final NodeIdentifier labelStackNid, final NodeIdentifier labelValueNid) {
156         final List<LabelStack> labels = new ArrayList<>();
157         final Optional<DataContainerChild<? extends PathArgument, ?>> labelStacks = route.getChild(labelStackNid);
158         if (labelStacks.isPresent()) {
159             for (final UnkeyedListEntryNode label : ((UnkeyedListNode) labelStacks.get()).getValue()) {
160                 final Optional<DataContainerChild<? extends PathArgument, ?>> labelStack
161                         = label.getChild(labelValueNid);
162                 if (labelStack.isPresent()) {
163                     final LabelStackBuilder labelStackbuilder = new LabelStackBuilder();
164                     labelStackbuilder.setLabelValue(new MplsLabel((Long) labelStack.get().getValue()));
165                     labels.add(labelStackbuilder.build());
166                 }
167             }
168         }
169         return labels;
170     }
171
172     @Override
173     public final LabeledUnicastRouteKey createRouteListKey(final PathId pathId, final String routeKey) {
174         return new LabeledUnicastRouteKey(pathId, routeKey);
175     }
176
177     @Override
178     public final LabeledUnicastRoute createRoute(final LabeledUnicastRoute route, final LabeledUnicastRouteKey key,
179             final Attributes attributes) {
180         final LabeledUnicastRouteBuilder builder;
181         if (route != null) {
182             builder = new LabeledUnicastRouteBuilder(route);
183         } else {
184             builder = new LabeledUnicastRouteBuilder();
185         }
186         return builder.withKey(key).setAttributes(attributes).build();
187     }
188
189     @Override
190     public final PathId extractPathId(final LabeledUnicastRouteKey routeListKey) {
191         return routeListKey.getPathId();
192     }
193
194     @Override
195     public final String extractRouteKey(final LabeledUnicastRouteKey routeListKey) {
196         return routeListKey.getRouteKey();
197     }
198 }