2 * Copyright (c) 2015 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.flowspec;
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;
56 final class FlowspecRIBSupport extends AbstractRIBSupport {
58 private abstract static class ApplyRoute {
59 abstract void apply(DOMDataWriteTransaction tx, YangInstanceIdentifier base, NodeIdentifierWithPredicates routeKey, DataContainerNode<?> route, final ContainerNode attributes);
62 private static final class DeleteRoute extends ApplyRoute {
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));
69 private final class PutRoute extends ApplyRoute {
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);
76 // FIXME: All route children, there should be a utility somewhere to do this
77 for (final DataContainerChild<? extends PathArgument, ?> child : route.getValue()) {
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());
88 private static final Logger LOG = LoggerFactory.getLogger(FlowspecRIBSupport.class);
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();
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();
104 private FlowspecRIBSupport() {
105 super(FlowspecRoutesCase.class, FlowspecRoutes.class, FlowspecRoute.class);
108 static FlowspecRIBSupport getInstance() {
113 public ChoiceNode emptyRoutes() {
114 return this.emptyRoutes;
118 public ImmutableCollection<Class<? extends DataObject>> cacheableAttributeObjects() {
119 return ImmutableSet.of();
123 public ImmutableCollection<Class<? extends DataObject>> cacheableNlriObjects() {
124 return ImmutableSet.of();
128 public boolean isComplexRoute() {
133 protected NodeIdentifier destinationContainerIdentifier() {
134 return this.destination;
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);
150 LOG.warn("Routes {} are not a map", routes);
157 protected void deleteDestinationRoutes(final DOMDataWriteTransaction tx, final YangInstanceIdentifier tablePath,
158 final ContainerNode destination) {
159 processDestination(tx, tablePath, destination, null, DELETE_ROUTE);
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);
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);
175 final List<Flowspec> dests = new ArrayList<>(routes.size());
176 for (final MapEntryNode reachRoute : routes) {
177 dests.add(FSNlriParser.extractFlowspec(reachRoute));
179 mb.setAdvertizedRoutes(new AdvertizedRoutesBuilder().setDestinationType(
180 new DestinationFlowspecCaseBuilder().setDestinationFlowspec(
181 new DestinationFlowspecBuilder().setFlowspec(dests).build()).build()).build());
186 protected MpUnreachNlri buildUnreach(final Collection<MapEntryNode> routes) {
187 final MpUnreachNlriBuilder mb = new MpUnreachNlriBuilder();
188 mb.setAfi(Ipv4AddressFamily.class);
189 mb.setSafi(FlowspecSubsequentAddressFamily.class);
191 final List<Flowspec> dests = new ArrayList<>(routes.size());
192 for (final MapEntryNode unreachRoute : routes) {
193 dests.add(FSNlriParser.extractFlowspec(unreachRoute));
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());