2 * Copyright (c) 2018 AT&T Intellectual Property. 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.openconfig.routing.policy.statement.conditions;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.cache.CacheBuilder;
13 import com.google.common.cache.CacheLoader;
14 import com.google.common.cache.LoadingCache;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.List;
18 import java.util.Objects;
19 import java.util.Optional;
20 import java.util.concurrent.ExecutionException;
21 import java.util.stream.Collectors;
22 import java.util.stream.Stream;
23 import org.apache.commons.lang3.StringUtils;
24 import org.opendaylight.mdsal.binding.api.DataBroker;
25 import org.opendaylight.mdsal.binding.api.ReadTransaction;
26 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
27 import org.opendaylight.protocol.bgp.openconfig.routing.policy.spi.RouteEntryBaseAttributes;
28 import org.opendaylight.protocol.bgp.openconfig.routing.policy.spi.policy.condition.BgpConditionsPolicy;
29 import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRouteEntryExportParameters;
30 import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRouteEntryImportParameters;
31 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.DefinedSets1;
32 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.bgp.match.conditions.MatchAsPathSet;
33 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.routing.policy.defined.sets.BgpDefinedSets;
34 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.routing.policy.defined.sets.bgp.defined.sets.AsPathSets;
35 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.routing.policy.defined.sets.bgp.defined.sets.as.path.sets.AsPathSet;
36 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.routing.policy.defined.sets.bgp.defined.sets.as.path.sets.AsPathSetKey;
37 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.AfiSafiType;
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.rev180329.path.attributes.Attributes;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.attributes.AsPath;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.attributes.as.path.Segments;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.AsPathSegment;
46 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
49 * Match a set of AS (All, ANY, INVERT).
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>() {
60 public AsPathSet load(final String key) throws ExecutionException, InterruptedException {
65 public MatchAsPathSetHandler(final DataBroker dataBroker) {
66 this.dataBroker = requireNonNull(dataBroker);
69 private AsPathSet loadSets(final String key) throws ExecutionException, InterruptedException {
70 final ReadTransaction 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.orElse(null);
77 public boolean matchImportCondition(
78 final Class<? extends AfiSafiType> afiSafi,
79 final RouteEntryBaseAttributes routeEntryInfo,
80 final BGPRouteEntryImportParameters routeEntryImportParameters,
82 final MatchAsPathSet conditions) {
83 return matchAsPathSetCondition(asPath, conditions.getAsPathSet(),
84 conditions.getMatchSetOptions());
89 public boolean matchExportCondition(
90 final Class<? extends AfiSafiType> afiSafi,
91 final RouteEntryBaseAttributes routeEntryInfo,
92 final BGPRouteEntryExportParameters routeEntryExportParameters,
94 final MatchAsPathSet conditions) {
95 return matchAsPathSetCondition(asPath, conditions.getAsPathSet(),
96 conditions.getMatchSetOptions());
101 public AsPath getConditionParameter(final Attributes attributes) {
102 return attributes.getAsPath();
106 private boolean matchAsPathSetCondition(final AsPath asPath, final String asPathSetName,
107 final MatchSetOptionsType matchSetOptions) {
108 if (asPath == null) {
111 final AsPathSet asPathSetFilter = this.sets.getUnchecked(StringUtils
112 .substringBetween(asPathSetName, "=\"", "\""));
114 final List<Segments> segments = asPath.getSegments();
115 if (asPathSetFilter == null || segments == null) {
119 final List<AsNumber> l1 = segments.stream()
120 .map(AsPathSegment::getAsSequence)
121 .filter(Objects::nonNull)
122 .flatMap(Collection::stream)
123 .filter(Objects::nonNull)
124 .collect(Collectors.toList());
126 final List<AsNumber> l2 = segments.stream()
127 .map(AsPathSegment::getAsSet)
128 .filter(Objects::nonNull)
129 .flatMap(Collection::stream)
130 .filter(Objects::nonNull)
131 .collect(Collectors.toList());
133 List<AsNumber> allAs = Stream.of(l1, l2).flatMap(Collection::stream).collect(Collectors.toList());
135 final List<AsNumber> asPathSetFilterList = asPathSetFilter.getAsPathSetMember();
136 if (matchSetOptions.equals(MatchSetOptionsType.ALL)) {
137 return allAs.containsAll(asPathSetFilterList)
138 && asPathSetFilterList.containsAll(allAs);
140 final boolean noneInCommon = Collections.disjoint(allAs, asPathSetFilterList);
141 if (matchSetOptions.equals(MatchSetOptionsType.ANY)) {
142 return !noneInCommon;
144 //(matchSetOptions.equals(MatchSetOptionsType.INVERT))