5539db68b41583545c9468b2275e7e76aef226a4
[bgpcep.git] / bgp / flowspec / src / main / java / org / opendaylight / protocol / bgp / flowspec / FlowspecRIBSupport.java
1 /*
2  * Copyright (c) 2015 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.flowspec;
9
10 import com.google.common.base.Optional;
11 import com.google.common.collect.ImmutableCollection;
12 import com.google.common.collect.ImmutableSet;
13 import java.util.ArrayList;
14 import java.util.Collection;
15 import java.util.List;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
18 import org.opendaylight.protocol.bgp.rib.spi.AbstractRIBSupport;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.FlowspecSubsequentAddressFamily;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.bgp.rib.rib.loc.rib.tables.routes.FlowspecRoutesCase;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.destination.Flowspec;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.routes.FlowspecRoutes;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.flowspec.routes.flowspec.routes.FlowspecRoute;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.attributes.mp.reach.nlri.advertized.routes.destination.type.DestinationFlowspecCaseBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.flowspec._case.DestinationFlowspec;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.attributes.mp.reach.nlri.advertized.routes.destination.type.destination.flowspec._case.DestinationFlowspecBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlri;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpReachNlriBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlri;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.MpUnreachNlriBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.reach.nlri.AdvertizedRoutesBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.multiprotocol.rev130919.update.attributes.mp.unreach.nlri.WithdrawnRoutesBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.rib.rev130925.rib.tables.Routes;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.Ipv4AddressFamily;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.CNextHop;
36 import org.opendaylight.yangtools.yang.binding.DataObject;
37 import org.opendaylight.yangtools.yang.common.QName;
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.YangInstanceIdentifier.PathArgument;
42 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
43 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
44 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
45 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
46 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
47 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
48 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
49 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
50 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
51 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
52 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56 final class FlowspecRIBSupport extends AbstractRIBSupport {
57
58     private abstract static class ApplyRoute {
59         abstract void apply(DOMDataWriteTransaction tx, YangInstanceIdentifier base, NodeIdentifierWithPredicates routeKey, DataContainerNode<?> route, final ContainerNode attributes);
60     }
61
62     private static final class DeleteRoute extends ApplyRoute {
63         @Override
64         void apply(final DOMDataWriteTransaction tx, final YangInstanceIdentifier base, final NodeIdentifierWithPredicates routeKey, final DataContainerNode<?> route, final ContainerNode attributes) {
65             tx.delete(LogicalDatastoreType.OPERATIONAL, base.node(routeKey));
66         }
67     }
68
69     private final class PutRoute extends ApplyRoute {
70         @Override
71         void apply(final DOMDataWriteTransaction tx, final YangInstanceIdentifier base, final NodeIdentifierWithPredicates routeKey,
72             final DataContainerNode<?> route, final ContainerNode attributes) {
73             final DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> b = ImmutableNodes.mapEntryBuilder();
74             b.withNodeIdentifier(routeKey);
75
76             // FIXME: All route children, there should be a utility somewhere to do this
77             for (final DataContainerChild<? extends PathArgument, ?> child : route.getValue()) {
78                 b.withChild(child);
79             }
80             // Add attributes
81             final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> cb = Builders.containerBuilder(attributes);
82             cb.withNodeIdentifier(routeAttributesIdentifier());
83             b.withChild(cb.build());
84             tx.put(LogicalDatastoreType.OPERATIONAL, base.node(routeKey), b.build());
85         }
86     }
87
88     private static final Logger LOG = LoggerFactory.getLogger(FlowspecRIBSupport.class);
89
90     private static final QName ROUTE_KEY = QName.cachedReference(QName.create(FlowspecRoute.QNAME, "route-key"));
91     private static final FlowspecRIBSupport SINGLETON = new FlowspecRIBSupport();
92     private static final ApplyRoute DELETE_ROUTE = new DeleteRoute();
93
94     private final ChoiceNode emptyRoutes = Builders.choiceBuilder()
95         .withNodeIdentifier(new NodeIdentifier(Routes.QNAME))
96         .addChild(Builders.containerBuilder()
97             .withNodeIdentifier(new NodeIdentifier(FlowspecRoutes.QNAME))
98             .addChild(ImmutableNodes.mapNodeBuilder(FlowspecRoute.QNAME).build()).build()).build();
99     private final NodeIdentifier destination = new NodeIdentifier(DestinationFlowspec.QNAME);
100     private final NodeIdentifier route = new NodeIdentifier(FlowspecRoute.QNAME);
101     private final NodeIdentifier nlriRoutesList = new NodeIdentifier(Flowspec.QNAME);
102     private final ApplyRoute putRoute = new PutRoute();
103
104     private FlowspecRIBSupport() {
105         super(FlowspecRoutesCase.class, FlowspecRoutes.class, FlowspecRoute.class);
106     }
107
108     static FlowspecRIBSupport getInstance() {
109         return SINGLETON;
110     }
111
112     @Override
113     public ChoiceNode emptyRoutes() {
114         return this.emptyRoutes;
115     }
116
117     @Override
118     public ImmutableCollection<Class<? extends DataObject>> cacheableAttributeObjects() {
119         return ImmutableSet.of();
120     }
121
122     @Override
123     public ImmutableCollection<Class<? extends DataObject>> cacheableNlriObjects() {
124         return ImmutableSet.of();
125     }
126
127     @Override
128     public boolean isComplexRoute() {
129         return true;
130     }
131
132     @Override
133     protected NodeIdentifier destinationContainerIdentifier() {
134         return this.destination;
135     }
136
137     private void processDestination(final DOMDataWriteTransaction tx, final YangInstanceIdentifier tablePath,
138         final ContainerNode destination, final ContainerNode attributes, final ApplyRoute function) {
139         if (destination != null) {
140             final Optional<DataContainerChild<? extends PathArgument, ?>> maybeRoutes = destination.getChild(this.nlriRoutesList);
141             if (maybeRoutes.isPresent()) {
142                 final DataContainerChild<? extends PathArgument, ?> routes = maybeRoutes.get();
143                 if (routes instanceof UnkeyedListNode) {
144                     final YangInstanceIdentifier base = tablePath.node(ROUTES).node(routesContainerIdentifier()).node(this.route);
145                     for (final UnkeyedListEntryNode e : ((UnkeyedListNode)routes).getValue()) {
146                         final NodeIdentifierWithPredicates routeKey = new NodeIdentifierWithPredicates(FlowspecRoute.QNAME, ROUTE_KEY, FSNlriParser.stringNlri(e));
147                         function.apply(tx, base, routeKey,  e, attributes);
148                     }
149                 } else {
150                     LOG.warn("Routes {} are not a map", routes);
151                 }
152             }
153         }
154     }
155
156     @Override
157     protected void deleteDestinationRoutes(final DOMDataWriteTransaction tx, final YangInstanceIdentifier tablePath,
158         final ContainerNode destination) {
159         processDestination(tx, tablePath, destination, null, DELETE_ROUTE);
160     }
161
162     @Override
163     protected void putDestinationRoutes(final DOMDataWriteTransaction tx, final YangInstanceIdentifier tablePath,
164         final ContainerNode destination, final ContainerNode attributes) {
165         processDestination(tx, tablePath, destination, attributes, this.putRoute);
166     }
167
168     @Override
169     protected MpReachNlri buildReach(final Collection<MapEntryNode> routes, final CNextHop hop) {
170         final MpReachNlriBuilder mb = new MpReachNlriBuilder();
171         mb.setAfi(Ipv4AddressFamily.class);
172         mb.setSafi(FlowspecSubsequentAddressFamily.class);
173         mb.setCNextHop(hop);
174
175         final List<Flowspec> dests = new ArrayList<>(routes.size());
176         for (final MapEntryNode reachRoute : routes) {
177             dests.add(FSNlriParser.extractFlowspec(reachRoute));
178         }
179         mb.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(
180             new DestinationFlowspecCaseBuilder().setDestinationFlowspec(
181                 new DestinationFlowspecBuilder().setFlowspec(dests).build()).build()).build());
182         return mb.build();
183     }
184
185     @Override
186     protected MpUnreachNlri buildUnreach(final Collection<MapEntryNode> routes) {
187         final MpUnreachNlriBuilder mb = new MpUnreachNlriBuilder();
188         mb.setAfi(Ipv4AddressFamily.class);
189         mb.setSafi(FlowspecSubsequentAddressFamily.class);
190
191         final List<Flowspec> dests = new ArrayList<>(routes.size());
192         for (final MapEntryNode unreachRoute : routes) {
193             dests.add(FSNlriParser.extractFlowspec(unreachRoute));
194         }
195         mb.setWithdrawnRoutes(new WithdrawnRoutesBuilder().setDestinationType(
196             new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.DestinationFlowspecCaseBuilder().setDestinationFlowspec(
197                 new org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.flowspec.rev150114.update.attributes.mp.unreach.nlri.withdrawn.routes.destination.type.destination.flowspec._case.DestinationFlowspecBuilder().setFlowspec(dests).build()).build()).build());
198         return mb.build();
199     }
200 }