e5e5b85c89b6c32873608e42573dbcb8a657d093
[bgpcep.git] / bgp / openconfig-rp-statement / src / main / java / org / opendaylight / protocol / bgp / openconfig / routing / policy / statement / conditions / MatchAsPathSetHandler.java
1 /*
2  * Copyright (c) 2018 AT&T Intellectual Property. 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
9 package org.opendaylight.protocol.bgp.openconfig.routing.policy.statement.conditions;
10
11 import static java.util.Objects.requireNonNull;
12
13 import com.google.common.base.Optional;
14 import com.google.common.cache.CacheBuilder;
15 import com.google.common.cache.CacheLoader;
16 import com.google.common.cache.LoadingCache;
17 import java.util.Collection;
18 import java.util.Collections;
19 import java.util.List;
20 import java.util.Objects;
21 import java.util.concurrent.ExecutionException;
22 import java.util.stream.Collectors;
23 import java.util.stream.Stream;
24 import org.apache.commons.lang3.StringUtils;
25 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
27 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
28 import org.opendaylight.protocol.bgp.openconfig.routing.policy.spi.RouteEntryBaseAttributes;
29 import org.opendaylight.protocol.bgp.openconfig.routing.policy.spi.policy.condition.BgpConditionsPolicy;
30 import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRouteEntryExportParameters;
31 import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRouteEntryImportParameters;
32 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.DefinedSets1;
33 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.bgp.match.conditions.MatchAsPathSet;
34 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.routing.policy.defined.sets.BgpDefinedSets;
35 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.routing.policy.defined.sets.bgp.defined.sets.AsPathSets;
36 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.routing.policy.defined.sets.bgp.defined.sets.as.path.sets.AsPathSet;
37 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.routing.policy.defined.sets.bgp.defined.sets.as.path.sets.AsPathSetKey;
38 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.policy.types.rev151009.MatchSetOptionsType;
39 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.routing.policy.rev151009.routing.policy.top.RoutingPolicy;
40 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.routing.policy.rev151009.routing.policy.top.routing.policy.DefinedSets;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.path.attributes.Attributes;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.path.attributes.attributes.AsPath;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.path.attributes.attributes.as.path.Segments;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.AsPathSegment;
46 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
47
48 /**
49  * Match a set of AS (All, ANY, INVERT).
50  */
51 public final class MatchAsPathSetHandler implements BgpConditionsPolicy<MatchAsPathSet, AsPath> {
52     private static final InstanceIdentifier<AsPathSets> AS_PATHS_SETS_IID
53             = InstanceIdentifier.create(RoutingPolicy.class).child(DefinedSets.class)
54             .augmentation(DefinedSets1.class).child(BgpDefinedSets.class)
55             .child(AsPathSets.class);
56     private final DataBroker dataBroker;
57     private final LoadingCache<String, AsPathSet> sets = CacheBuilder.newBuilder()
58             .build(new CacheLoader<String, AsPathSet>() {
59                 @Override
60                 public AsPathSet load(final String key) throws ExecutionException, InterruptedException {
61                     return loadSets(key);
62                 }
63             });
64
65     public MatchAsPathSetHandler(final DataBroker dataBroker) {
66         this.dataBroker = requireNonNull(dataBroker);
67     }
68
69     private AsPathSet loadSets(final String key) throws ExecutionException, InterruptedException {
70         final ReadOnlyTransaction tr = this.dataBroker.newReadOnlyTransaction();
71         final Optional<AsPathSet> result = tr.read(LogicalDatastoreType.CONFIGURATION,
72                 AS_PATHS_SETS_IID.child(AsPathSet.class, new AsPathSetKey(key))).get();
73         return result.orNull();
74     }
75
76     @Override
77     public boolean matchImportCondition(
78             final RouteEntryBaseAttributes routeEntryInfo,
79             final BGPRouteEntryImportParameters routeEntryImportParameters,
80             final AsPath asPath,
81             final MatchAsPathSet conditions) {
82         return matchAsPathSetCondition(asPath, conditions.getAsPathSet(),
83                 conditions.getMatchSetOptions());
84     }
85
86
87     @Override
88     public boolean matchExportCondition(
89             final RouteEntryBaseAttributes routeEntryInfo,
90             final BGPRouteEntryExportParameters routeEntryExportParameters,
91             final AsPath asPath,
92             final MatchAsPathSet conditions) {
93         return matchAsPathSetCondition(asPath, conditions.getAsPathSet(),
94                 conditions.getMatchSetOptions());
95
96     }
97
98     @Override
99     public AsPath getConditionParameter(final Attributes attributes) {
100         return attributes.getAsPath();
101     }
102
103
104     private boolean matchAsPathSetCondition(final AsPath asPath, final String asPathSetName,
105             final MatchSetOptionsType matchSetOptions) {
106         if (asPath == null) {
107             return false;
108         }
109         final AsPathSet asPathSetFilter = this.sets.getUnchecked(StringUtils
110                 .substringBetween(asPathSetName, "=\"", "\""));
111
112         final List<Segments> segments = asPath.getSegments();
113         if (asPathSetFilter == null || segments == null) {
114             return false;
115         }
116
117         final List<AsNumber> l1 = segments.stream()
118                 .map(AsPathSegment::getAsSequence)
119                 .filter(Objects::nonNull)
120                 .flatMap(Collection::stream)
121                 .filter(Objects::nonNull)
122                 .collect(Collectors.toList());
123
124         final List<AsNumber> l2 = segments.stream()
125                 .map(AsPathSegment::getAsSet)
126                 .filter(Objects::nonNull)
127                 .flatMap(Collection::stream)
128                 .filter(Objects::nonNull)
129                 .collect(Collectors.toList());
130
131         List<AsNumber> allAs = Stream.of(l1, l2).flatMap(Collection::stream).collect(Collectors.toList());
132
133         final List<AsNumber> asPathSetFilterList = asPathSetFilter.getAsPathSetMember();
134         if (matchSetOptions.equals(MatchSetOptionsType.ALL)) {
135             return allAs.containsAll(asPathSetFilterList)
136                     && asPathSetFilterList.containsAll(allAs);
137         }
138         final boolean noneInCommon = Collections.disjoint(allAs, asPathSetFilterList);
139         if (matchSetOptions.equals(MatchSetOptionsType.ANY)) {
140             return !noneInCommon;
141         }
142         //(matchSetOptions.equals(MatchSetOptionsType.INVERT))
143         return noneInCommon;
144     }
145 }