Bump upstreams to 2022.09
[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.stream.Collectors;
17 import org.eclipse.jdt.annotation.NonNull;
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.rib.rev180329.rib.tables.Routes;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev200120.AddressFamily;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.concepts.rev131125.MplsLabel;
34 import org.opendaylight.yangtools.yang.binding.ChildOf;
35 import org.opendaylight.yangtools.yang.binding.DataObject;
36 import org.opendaylight.yangtools.yang.common.QName;
37 import org.opendaylight.yangtools.yang.common.Uint32;
38 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
39 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
40 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
41 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
42 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
43 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
44 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
45 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
46 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
47 import org.slf4j.Logger;
48 import org.slf4j.LoggerFactory;
49
50 abstract class AbstractLabeledUnicastRIBSupport<
51         C extends Routes & DataObject,
52         S extends ChildOf<? super C> & LabeledUnicastRoutesList>
53         extends AbstractRIBSupport<C, S, LabeledUnicastRoute> {
54     private static final NodeIdentifier LABEL_STACK_NID
55             = NodeIdentifier.create(QName.create(CLabeledUnicastDestination.QNAME, "label-stack").intern());
56     private static final NodeIdentifier LV_NID
57             = NodeIdentifier.create(QName.create(CLabeledUnicastDestination.QNAME, "label-value").intern());
58     private static final NodeIdentifier NLRI_ROUTES_LIST = NodeIdentifier.create(CLabeledUnicastDestination.QNAME);
59     private static final Logger LOG = LoggerFactory.getLogger(AbstractLabeledUnicastRIBSupport.class);
60
61     /**
62      * Default constructor. Requires the QName of the container augmented under the routes choice
63      * node in instantiations of the rib grouping. It is assumed that this container is defined by
64      * the same model which populates it with route grouping instantiation, and by extension with
65      * the route attributes container.
66      * @param mappingService  Binding Normalized Node Serializer
67      * @param cazeClass Binding class of the AFI/SAFI-specific case statement, must not be null
68      * @param containerClass Binding class of the container in routes choice, must not be null.
69      * @param addressFamilyClass address Family Class
70      * @param destinationQname destination Qname
71      */
72     AbstractLabeledUnicastRIBSupport(
73             final BindingNormalizedNodeSerializer mappingService,
74             final Class<C> cazeClass,
75             final Class<S> containerClass,
76             final AddressFamily addressFamilyClass,
77             final QName destinationQname) {
78         super(mappingService,
79                 cazeClass,
80                 containerClass,
81                 LabeledUnicastRoute.class,
82                 addressFamilyClass,
83                 LabeledUnicastSubsequentAddressFamily.VALUE,
84                 destinationQname);
85     }
86
87     @Override
88     protected Collection<NodeIdentifierWithPredicates> processDestination(final DOMDataTreeWriteTransaction tx,
89                                                                           final YangInstanceIdentifier routesPath,
90                                                                           final ContainerNode destination,
91                                                                           final ContainerNode attributes,
92                                                                           final ApplyRoute function) {
93         if (destination != null) {
94             final DataContainerChild routes = destination.childByArg(NLRI_ROUTES_LIST);
95             if (routes != null) {
96                 if (routes instanceof UnkeyedListNode) {
97                     final YangInstanceIdentifier base = routesYangInstanceIdentifier(routesPath);
98                     final Collection<UnkeyedListEntryNode> routesList = ((UnkeyedListNode) routes).body();
99                     final List<NodeIdentifierWithPredicates> keys = new ArrayList<>(routesList.size());
100                     for (final UnkeyedListEntryNode labeledUcastDest : routesList) {
101                         final NodeIdentifierWithPredicates routeKey = createRouteKey(labeledUcastDest);
102                         function.apply(tx, base, routeKey, labeledUcastDest, attributes);
103                         keys.add(routeKey);
104                     }
105                     return keys;
106                 }
107                 LOG.warn("Routes {} are not a map", routes);
108             }
109         }
110         return Collections.emptyList();
111     }
112
113
114     protected List<CLabeledUnicastDestination> extractRoutes(final Collection<MapEntryNode> routes) {
115         return routes.stream().map(this::extractCLabeledUnicastDestination).collect(Collectors.toList());
116     }
117
118     private NodeIdentifierWithPredicates createRouteKey(final UnkeyedListEntryNode labeledUnicast) {
119         final ByteBuf buffer = Unpooled.buffer();
120
121         final CLabeledUnicastDestination dest = extractCLabeledUnicastDestination(labeledUnicast);
122         LUNlriParser.serializeNlri(Collections.singletonList(dest), false, buffer);
123         final String routeKeyValue = ByteArray.encodeBase64(buffer);
124         return PathIdUtil.createNidKey(routeQName(), routeKeyTemplate(), routeKeyValue,
125             labeledUnicast.findChildByArg(routePathIdNid()));
126     }
127
128     /**
129      * Conversion from DataContainer to LabeledUnicastDestination Object.
130      *
131      * @param route DataContainer
132      * @return LabeledUnicastDestination Object
133      */
134     private CLabeledUnicastDestination extractCLabeledUnicastDestination(final DataContainerNode route) {
135         final DataContainerChild child = route.childByArg(prefixNid());
136
137         return new CLabeledUnicastDestinationBuilder()
138             .setPrefix(child == null ? null : createIpPrefix((String) child.body()))
139             .setLabelStack(extractLabel(route, LABEL_STACK_NID, LV_NID))
140             .setPathId(PathIdUtil.buildPathId(route, routePathIdNid()))
141             .build();
142     }
143
144     protected abstract @NonNull IpPrefix createIpPrefix(@NonNull String prefixString);
145
146     public static List<LabelStack> extractLabel(final DataContainerNode route, final NodeIdentifier labelStackNid,
147             final NodeIdentifier labelValueNid) {
148         final List<LabelStack> labels = new ArrayList<>();
149         final DataContainerChild labelStacks = route.childByArg(labelStackNid);
150         if (labelStacks != null) {
151             for (final UnkeyedListEntryNode label : ((UnkeyedListNode) labelStacks).body()) {
152                 final DataContainerChild labelStack = label.childByArg(labelValueNid);
153                 if (labelStack != null) {
154                     labels.add(new LabelStackBuilder()
155                         .setLabelValue(new MplsLabel((Uint32) labelStack.body()))
156                         .build());
157                 }
158             }
159         }
160         return labels;
161     }
162 }