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
9 package org.opendaylight.protocol.bgp.openconfig.routing.policy.spi.registry;
11 import static java.util.Objects.requireNonNull;
12 import static org.opendaylight.yang.gen.v1.http.openconfig.net.yang.policy.types.rev151009.MatchSetOptionsRestrictedType.ANY;
14 import com.google.common.cache.CacheBuilder;
15 import com.google.common.cache.CacheLoader;
16 import com.google.common.cache.LoadingCache;
17 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.List;
22 import java.util.concurrent.ExecutionException;
23 import java.util.stream.Collectors;
24 import javax.annotation.Nonnull;
25 import org.apache.commons.lang3.StringUtils;
26 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
27 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
28 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
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.routing.policy.rev151009.GenericConditions;
32 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.routing.policy.rev151009.generic.conditions.MatchPrefixSet;
33 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.routing.policy.rev151009.generic.defined.sets.PrefixSets;
34 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.routing.policy.rev151009.prefix.set.PrefixSet;
35 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.routing.policy.rev151009.prefix.set.PrefixSetKey;
36 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.routing.policy.rev151009.prefix.set.prefix.set.Prefix;
37 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.routing.policy.rev151009.routing.policy.top.RoutingPolicy;
38 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.routing.policy.rev151009.routing.policy.top.routing.policy.DefinedSets;
39 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev171207.ipv4.routes.ipv4.routes.Ipv4Route;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.inet.rev171207.ipv6.routes.ipv6.routes.Ipv6Route;
44 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
45 import org.opendaylight.yangtools.yang.common.QName;
46 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
48 @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE")
49 final class GenericConditionPolicyHandler {
50 private static final InstanceIdentifier<PrefixSets> PREFIXES_SET_IID
51 = InstanceIdentifier.create(RoutingPolicy.class).child(DefinedSets.class)
52 .child(PrefixSets.class);
53 private static final QName IPV4_PREFIX_QNAME = QName.create(Ipv4Route.QNAME, "prefix").intern();
54 private static final QName IPV6_PREFIX_QNAME = QName.create(Ipv6Route.QNAME, "prefix").intern();
55 private static final String EXACT = "exact";
56 private final DataBroker databroker;
57 private final LoadingCache<String, List<Prefix>> prefixSets = CacheBuilder.newBuilder()
58 .build(new CacheLoader<String, List<Prefix>>() {
60 public List<Prefix> load(final String key) throws ExecutionException, InterruptedException {
61 return loadPrefixSets(key);
65 private final LoadingCache<String, List<IpPrefix>> prefixes = CacheBuilder.newBuilder()
66 .build(new CacheLoader<String, List<IpPrefix>>() {
68 public List<IpPrefix> load(final String key) {
69 final List<Prefix> prefixSet = GenericConditionPolicyHandler.this.prefixSets.getUnchecked(key);
71 .stream().map(GenericConditionPolicyHandler::createPrefixes).flatMap(List::stream)
72 .collect(Collectors.toList());
76 GenericConditionPolicyHandler(final DataBroker databroker) {
77 this.databroker = requireNonNull(databroker);
80 private static List<IpPrefix> createPrefixes(final Prefix prefixContainer) {
81 final IpPrefix prefix = prefixContainer.getIpPrefix();
82 if (prefixContainer.getMasklengthRange().equals(EXACT)) {
83 return Collections.singletonList(prefix);
86 final String[] range = prefixContainer.getMasklengthRange().split("\\..");
89 final String prefixString;
90 if (prefix.getIpv4Prefix() != null) {
91 prefixString = prefix.getIpv4Prefix().getValue();
94 prefixString = prefix.getIpv6Prefix().getValue();
97 int from = Integer.parseInt(range[0]);
99 final List<IpPrefix> prefixes = new ArrayList<>();
100 while (from <= Integer.parseInt(range[1])) {
101 final String prefixVal = StringUtils.replacePattern(prefixString,
102 "[/][0-9]+", "/" + Integer.toString(from));
104 prefixes.add(new IpPrefix(new Ipv4Prefix(prefixVal)));
106 prefixes.add(new IpPrefix(new Ipv6Prefix(prefixVal)));
113 private List<Prefix> loadPrefixSets(final String key) throws ExecutionException, InterruptedException {
114 final ReadOnlyTransaction tr = this.databroker.newReadOnlyTransaction();
115 final com.google.common.base.Optional<PrefixSet> result =
116 tr.read(LogicalDatastoreType.CONFIGURATION, PREFIXES_SET_IID
117 .child(PrefixSet.class, new PrefixSetKey(key))).get();
118 if (!result.isPresent()) {
119 return Collections.emptyList();
121 return result.get().getPrefix();
124 public boolean matchImportCondition(final BGPRouteEntryImportParameters routeEntryImportParameters,
125 final GenericConditions conditions) {
126 final MatchPrefixSet prefixSet = conditions.getMatchPrefixSet();
129 /*return prefixSet == null
130 || !matchPrefix(routeEntryImportParameters.getRouteId(), conditions.getMatchPrefixSet());*/
133 public boolean matchExportCondition(final BGPRouteEntryExportParameters routeEntryExportParameters,
134 final GenericConditions conditions) {
135 final MatchPrefixSet prefixSet = conditions.getMatchPrefixSet();
138 /*return prefixSet == null
139 || matchPrefix(routeEntryExportParameters.getRouteId(), conditions.getMatchPrefixSet());*/
142 @SuppressFBWarnings("UPM_UNCALLED_PRIVATE_METHOD")
143 private boolean matchPrefix(
144 final NodeIdentifierWithPredicates routeId,
145 final MatchPrefixSet matchPrefixSet) {
146 final String prefixKey = StringUtils.substringBetween(matchPrefixSet.getPrefixSet(), "=\"", "\"");
147 final boolean any = matchPrefixSet.getMatchSetOptions().equals(ANY);
148 final boolean found = this.prefixes.getUnchecked(prefixKey).contains(extractPrefix(routeId));
149 return any && found || !any && !found;
153 private IpPrefix extractPrefix(final NodeIdentifierWithPredicates routeId) {
154 final QName qName = routeId.getNodeType();
155 if (Ipv4Route.QNAME.equals(qName)) {
156 final Map<QName, Object> values = routeId.getKeyValues();
157 return new IpPrefix(new Ipv4Prefix((String) values.get(IPV4_PREFIX_QNAME)));
159 final Map<QName, Object> values = routeId.getKeyValues();
160 return new IpPrefix(new Ipv6Prefix((String) values.get(IPV6_PREFIX_QNAME)));