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.spi.registry;
10 import com.google.common.base.Preconditions;
11 import java.util.HashMap;
12 import java.util.List;
14 import java.util.Objects;
15 import javax.annotation.concurrent.GuardedBy;
16 import org.opendaylight.protocol.bgp.openconfig.routing.policy.spi.RouteEntryBaseAttributes;
17 import org.opendaylight.protocol.bgp.openconfig.routing.policy.spi.policy.condition.BgpConditionsAugmentationPolicy;
18 import org.opendaylight.protocol.bgp.openconfig.routing.policy.spi.policy.condition.BgpConditionsPolicy;
19 import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRouteEntryExportParameters;
20 import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRouteEntryImportParameters;
21 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.BgpMatchConditions;
22 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.Conditions1;
23 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.bgp.attribute.conditions.AsPathLength;
24 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.bgp.match.conditions.MatchAsPathSet;
25 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.bgp.match.conditions.MatchCommunitySet;
26 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.bgp.match.conditions.MatchExtCommunitySet;
27 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.routing.policy.policy.definitions.policy.definition.statements.statement.conditions.BgpConditions;
28 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.BgpOriginAttrType;
29 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.policy.types.rev151009.AttributeComparison;
30 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.policy.types.rev151009.AttributeEq;
31 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.policy.types.rev151009.AttributeGe;
32 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.policy.types.rev151009.AttributeLe;
33 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.routing.policy.rev151009.routing.policy.top.routing.policy.policy.definitions.policy.definition.statements.statement.Conditions;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.path.attributes.Attributes;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.path.attributes.attributes.AsPath;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.path.attributes.attributes.LocalPref;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.path.attributes.attributes.MultiExitDisc;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.path.attributes.attributes.Origin;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev171207.path.attributes.attributes.as.path.Segments;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.AsPathSegment;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.CNextHop;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.c.next.hop.EmptyNextHopCase;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.c.next.hop.Ipv4NextHopCase;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev130919.next.hop.c.next.hop.Ipv6NextHopCase;
46 import org.opendaylight.yangtools.concepts.AbstractRegistration;
47 import org.opendaylight.yangtools.yang.binding.Augmentation;
48 import org.opendaylight.yangtools.yang.binding.ChildOf;
49 import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
51 public final class BgpConditionsRegistry {
53 private final Map<Class<? extends Augmentation<BgpConditions>>,
54 BgpConditionsAugmentationPolicy> bgpConditionsAugRegistry = new HashMap<>();
56 private final Map<Class<? extends ChildOf<BgpMatchConditions>>,
57 BgpConditionsPolicy> bgpConditionsRegistry = new HashMap<>();
59 public AbstractRegistration registerBgpConditionsAugmentationPolicy(
60 final Class<? extends Augmentation<BgpConditions>> conditionPolicyClass,
61 final BgpConditionsAugmentationPolicy conditionPolicy) {
62 synchronized (this.bgpConditionsAugRegistry) {
63 final BgpConditionsAugmentationPolicy prev
64 = this.bgpConditionsAugRegistry.putIfAbsent(conditionPolicyClass, conditionPolicy);
65 Preconditions.checkState(prev == null, "Condition Policy %s already registered %s",
66 conditionPolicyClass, prev);
67 return new AbstractRegistration() {
69 protected void removeRegistration() {
70 synchronized (BgpConditionsRegistry.this.bgpConditionsAugRegistry) {
71 BgpConditionsRegistry.this.bgpConditionsAugRegistry.remove(conditionPolicyClass);
78 public <T extends ChildOf<BgpMatchConditions>, N> AbstractRegistration registerBgpConditionsPolicy(
79 final Class<T> conditionPolicyClass,
80 final BgpConditionsPolicy<T, N> conditionPolicy) {
81 synchronized (this.bgpConditionsRegistry) {
82 final BgpConditionsPolicy prev
83 = this.bgpConditionsRegistry.putIfAbsent(conditionPolicyClass, conditionPolicy);
84 Preconditions.checkState(prev == null, "Condition Policy %s already registered %s",
85 conditionPolicyClass, prev);
86 return new AbstractRegistration() {
88 protected void removeRegistration() {
89 synchronized (BgpConditionsRegistry.this.bgpConditionsRegistry) {
90 BgpConditionsRegistry.this.bgpConditionsRegistry.remove(conditionPolicyClass);
97 @SuppressWarnings("unchecked")
98 public boolean matchExportConditions(
99 final RouteEntryBaseAttributes entryInfo,
100 final BGPRouteEntryExportParameters routeEntryExportParameters,
101 final Attributes attributes,
102 final Conditions conditions) {
103 final Conditions1 bgpConditionsAug = conditions.getAugmentation(Conditions1.class);
104 if (bgpConditionsAug != null) {
106 final BgpConditions bgpConditions = bgpConditionsAug.getBgpConditions();
107 if (!matchExportCondition(entryInfo, routeEntryExportParameters, attributes,
111 final Map<Class<? extends Augmentation<?>>, Augmentation<?>> bgpAug = BindingReflections
112 .getAugmentations(bgpConditions);
113 for (final Map.Entry<Class<? extends Augmentation<?>>, Augmentation<?>> entry : bgpAug.entrySet()) {
114 final BgpConditionsAugmentationPolicy handler = this.bgpConditionsAugRegistry.get(entry.getKey());
115 if (handler == null) {
118 if (!handler.matchExportCondition(entryInfo, routeEntryExportParameters,
119 handler.getConditionParameter(attributes), entry.getValue())) {
128 public boolean matchImportConditions(
129 final RouteEntryBaseAttributes entryInfo,
130 final BGPRouteEntryImportParameters routeEntryImportParameters,
131 final Attributes attributes,
132 final Conditions conditions) {
134 final Conditions1 bgpConditionsAug = conditions.getAugmentation(Conditions1.class);
135 if (bgpConditionsAug != null) {
136 final BgpConditions bgpConditions = bgpConditionsAug.getBgpConditions();
137 synchronized (this) {
138 if (!matchImportCondition(entryInfo, routeEntryImportParameters, attributes,
143 final Map<Class<? extends Augmentation<?>>, Augmentation<?>> bgpAug = BindingReflections
144 .getAugmentations(bgpConditions);
145 for (final Map.Entry<Class<? extends Augmentation<?>>, Augmentation<?>> entry : bgpAug.entrySet()) {
146 final BgpConditionsAugmentationPolicy handler = this.bgpConditionsAugRegistry.get(entry.getKey());
147 if (handler == null) {
150 if (!handler.matchImportCondition(entryInfo, routeEntryImportParameters,
151 handler.getConditionParameter(attributes), entry.getValue())) {
159 @SuppressWarnings("unchecked")
160 private boolean matchImportCondition(
161 final RouteEntryBaseAttributes routeEntryInfo,
162 final BGPRouteEntryImportParameters routeEntryImportParameters,
163 final Attributes attributes,
164 final BgpConditions conditions) {
166 if (!matchAsPathLength(attributes.getAsPath(), conditions.getAsPathLength())) {
170 if (!matchMED(attributes.getMultiExitDisc(), conditions.getMedEq())) {
174 if (!matchOrigin(attributes.getOrigin(), conditions.getOriginEq())) {
178 if (!matchNextHopIn(attributes.getCNextHop(), conditions.getNextHopIn())) {
182 if (!matchLocalPref(attributes.getLocalPref(), conditions.getLocalPrefEq())) {
186 final MatchCommunitySet matchCond = conditions.getMatchCommunitySet();
187 if (matchCond != null) {
188 final BgpConditionsPolicy handler = this.bgpConditionsRegistry.get(MatchCommunitySet.class);
189 if (!handler.matchImportCondition(routeEntryInfo, routeEntryImportParameters,
190 handler.getConditionParameter(attributes), matchCond)) {
195 final MatchAsPathSet matchAsPathSet = conditions.getMatchAsPathSet();
196 if (matchCond != null) {
197 final BgpConditionsPolicy handler = this.bgpConditionsRegistry.get(MatchAsPathSet.class);
198 if (!handler.matchImportCondition(routeEntryInfo, routeEntryImportParameters,
199 handler.getConditionParameter(attributes), matchAsPathSet)) {
204 final MatchExtCommunitySet matchExtCommSet = conditions.getMatchExtCommunitySet();
205 if (matchExtCommSet != null) {
206 final BgpConditionsPolicy handler = this.bgpConditionsRegistry.get(MatchAsPathSet.class);
207 if (!handler.matchImportCondition(routeEntryInfo, routeEntryImportParameters,
208 handler.getConditionParameter(attributes), matchExtCommSet)) {
216 @SuppressWarnings("unchecked")
217 private boolean matchExportCondition(
218 final RouteEntryBaseAttributes routeEntryInfo,
219 final BGPRouteEntryExportParameters routeEntryExportParameters,
220 final Attributes attributes,
221 final BgpConditions conditions) {
222 if (!matchAsPathLength(attributes.getAsPath(), conditions.getAsPathLength())) {
226 if (!matchMED(attributes.getMultiExitDisc(), conditions.getMedEq())) {
230 if (!matchOrigin(attributes.getOrigin(), conditions.getOriginEq())) {
234 if (!matchNextHopIn(attributes.getCNextHop(), conditions.getNextHopIn())) {
238 if (!matchLocalPref(attributes.getLocalPref(), conditions.getLocalPrefEq())) {
242 final MatchCommunitySet matchCond = conditions.getMatchCommunitySet();
243 if (matchCond != null) {
244 final BgpConditionsPolicy handler = this.bgpConditionsRegistry.get(MatchCommunitySet.class);
245 if (!handler.matchExportCondition(routeEntryInfo, routeEntryExportParameters,
246 handler.getConditionParameter(attributes), matchCond)) {
251 final MatchAsPathSet matchAsPathSet = conditions.getMatchAsPathSet();
252 if (matchAsPathSet != null) {
253 final BgpConditionsPolicy handler = this.bgpConditionsRegistry.get(MatchAsPathSet.class);
254 if (!handler.matchExportCondition(routeEntryInfo, routeEntryExportParameters,
255 handler.getConditionParameter(attributes), matchAsPathSet)) {
260 final MatchExtCommunitySet matchExtCommSet = conditions.getMatchExtCommunitySet();
261 if (matchExtCommSet != null) {
262 final BgpConditionsPolicy handler = this.bgpConditionsRegistry.get(MatchExtCommunitySet.class);
263 if (!handler.matchExportCondition(routeEntryInfo, routeEntryExportParameters,
264 handler.getConditionParameter(attributes), matchExtCommSet)) {
272 private boolean matchMED(final MultiExitDisc multiExitDisc, final Long med) {
273 if (multiExitDisc == null || med == null) {
277 return multiExitDisc.getMed().equals(med);
280 private boolean matchOrigin(final Origin origin, final BgpOriginAttrType originEq) {
281 if (origin == null || originEq == null) {
284 return origin.getValue().getIntValue() == originEq.getIntValue();
287 private boolean matchAsPathLength(final AsPath asPath, final AsPathLength asPathLength) {
288 if (asPath == null || asPathLength == null) {
292 final List<Segments> segments = asPath.getSegments();
293 int total = segments.stream().map(AsPathSegment::getAsSequence)
294 .filter(Objects::nonNull).mapToInt(List::size).sum();
297 total = segments.stream().map(AsPathSegment::getAsSet)
298 .filter(Objects::nonNull).mapToInt(List::size).sum();
301 final Class<? extends AttributeComparison> comp = asPathLength.getOperator();
302 final long asPathLenght = asPathLength.getValue();
303 if (comp == AttributeEq.class) {
304 return total == asPathLenght;
305 } else if (comp == AttributeGe.class) {
306 return total >= asPathLenght;
307 } else if (comp == AttributeLe.class) {
308 return total <= asPathLenght;
314 private boolean matchNextHopIn(final CNextHop nextHop, final List<IpAddress> nextHopIn) {
315 if (nextHop == null || nextHopIn == null || nextHop instanceof EmptyNextHopCase) {
320 if (nextHop instanceof Ipv4NextHopCase) {
321 global = new IpAddress(((Ipv4NextHopCase) nextHop).getIpv4NextHop().getGlobal());
323 global = new IpAddress(((Ipv6NextHopCase) nextHop).getIpv6NextHop().getGlobal());
325 return nextHopIn.contains(global);
328 private boolean matchLocalPref(final LocalPref localPref, final Long localPrefEq) {
329 if (localPref == null || localPrefEq == null) {
332 return localPref.getPref().equals(localPrefEq);