Use moved BindingReflections
[bgpcep.git] / bgp / openconfig-rp-spi / src / main / java / org / opendaylight / protocol / bgp / openconfig / routing / policy / spi / registry / ActionsRegistryImpl.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 package org.opendaylight.protocol.bgp.openconfig.routing.policy.spi.registry;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.base.Preconditions;
13 import java.util.HashMap;
14 import java.util.Map;
15 import javax.annotation.concurrent.GuardedBy;
16 import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
17 import org.opendaylight.protocol.bgp.openconfig.routing.policy.spi.RouteEntryBaseAttributes;
18 import org.opendaylight.protocol.bgp.openconfig.routing.policy.spi.policy.action.ActionsAugPolicy;
19 import org.opendaylight.protocol.bgp.openconfig.routing.policy.spi.policy.action.BgpActionAugPolicy;
20 import org.opendaylight.protocol.bgp.openconfig.routing.policy.spi.policy.action.BgpActionPolicy;
21 import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRouteEntryExportParameters;
22 import org.opendaylight.protocol.bgp.rib.spi.policy.BGPRouteEntryImportParameters;
23 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.Actions1;
24 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.BgpNextHopType;
25 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.BgpSetMedType;
26 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.routing.policy.policy.definitions.policy.definition.statements.statement.actions.BgpActions;
27 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.routing.policy.policy.definitions.policy.definition.statements.statement.actions.bgp.actions.SetAsPathPrepend;
28 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.routing.policy.policy.definitions.policy.definition.statements.statement.actions.bgp.actions.SetCommunity;
29 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.policy.rev151009.routing.policy.policy.definitions.policy.definition.statements.statement.actions.bgp.actions.SetExtCommunity;
30 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.types.rev151009.BgpOriginAttrType;
31 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.routing.policy.rev151009.generic.actions.route.disposition.RejectRoute;
32 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.routing.policy.rev151009.routing.policy.top.routing.policy.policy.definitions.policy.definition.statements.statement.Actions;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.Attributes;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.AttributesBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.attributes.LocalPrefBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.attributes.MultiExitDiscBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.message.rev180329.path.attributes.attributes.OriginBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.BgpOrigin;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.next.hop.CNextHop;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.next.hop.c.next.hop.Ipv4NextHopCaseBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.next.hop.c.next.hop.Ipv6NextHopCaseBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.next.hop.c.next.hop.ipv4.next.hop._case.Ipv4NextHopBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.next.hop.c.next.hop.ipv6.next.hop._case.Ipv6NextHopBuilder;
45 import org.opendaylight.yangtools.concepts.AbstractRegistration;
46 import org.opendaylight.yangtools.yang.binding.Augmentation;
47 import org.opendaylight.yangtools.yang.binding.ChildOf;
48
49 final class ActionsRegistryImpl {
50     @GuardedBy("this")
51     private final Map<Class<? extends Augmentation<Actions>>, ActionsAugPolicy> actionsRegistry = new HashMap<>();
52     @GuardedBy("this")
53     private final Map<Class<? extends ChildOf<BgpActions>>, BgpActionPolicy> bgpActions = new HashMap<>();
54     @GuardedBy("this")
55     private final Map<Class<? extends Augmentation<BgpActions>>, BgpActionAugPolicy> bgpAugActionsRegistry
56             = new HashMap<>();
57
58     AbstractRegistration registerActionPolicy(
59             final Class<? extends Augmentation<Actions>> actionPolicyClass,
60             final ActionsAugPolicy actionPolicy) {
61         synchronized (this.actionsRegistry) {
62             final ActionsAugPolicy prev = this.actionsRegistry.putIfAbsent(actionPolicyClass, actionPolicy);
63             Preconditions.checkState(prev == null, "Action Policy %s already registered %s",
64                     actionPolicyClass, prev);
65             return new AbstractRegistration() {
66                 @Override
67                 protected void removeRegistration() {
68                     synchronized (ActionsRegistryImpl.this.actionsRegistry) {
69                         ActionsRegistryImpl.this.actionsRegistry.remove(actionPolicyClass);
70                     }
71                 }
72             };
73         }
74     }
75
76     public AbstractRegistration registerBgpActionPolicy(
77             final Class<? extends ChildOf<BgpActions>> bgpActionPolicyClass,
78             final BgpActionPolicy bgpActionPolicy) {
79         synchronized (this.bgpActions) {
80             final BgpActionPolicy prev = this.bgpActions.putIfAbsent(bgpActionPolicyClass, bgpActionPolicy);
81             Preconditions.checkState(prev == null, "Action Policy %s already registered %s",
82                     bgpActionPolicyClass, prev);
83             return new AbstractRegistration() {
84                 @Override
85                 protected void removeRegistration() {
86                     synchronized (ActionsRegistryImpl.this.bgpActions) {
87                         ActionsRegistryImpl.this.bgpActions.remove(bgpActionPolicyClass);
88                     }
89                 }
90             };
91         }
92     }
93
94     public AbstractRegistration registerBgpActionAugmentationPolicy(
95             final Class<? extends Augmentation<BgpActions>> bgpActionPolicyClass,
96             final BgpActionAugPolicy bgpActionPolicy) {
97         synchronized (this.bgpAugActionsRegistry) {
98             final BgpActionAugPolicy prev = this.bgpAugActionsRegistry
99                     .putIfAbsent(bgpActionPolicyClass, bgpActionPolicy);
100             Preconditions.checkState(prev == null, "Action Policy %s already registered %s",
101                     bgpActionPolicyClass, prev);
102             return new AbstractRegistration() {
103                 @Override
104                 protected void removeRegistration() {
105                     synchronized (ActionsRegistryImpl.this.bgpAugActionsRegistry) {
106                         ActionsRegistryImpl.this.bgpAugActionsRegistry.remove(bgpActionPolicyClass);
107                     }
108                 }
109             };
110         }
111     }
112
113     @SuppressWarnings("unchecked")
114     Attributes applyExportAction(
115             final RouteEntryBaseAttributes routeEntryInfo,
116             final BGPRouteEntryExportParameters routeEntryExportParameters,
117             final Attributes attributes,
118             final Actions actions) {
119         requireNonNull(attributes);
120         if (actions.getRouteDisposition() instanceof RejectRoute) {
121             return null;
122         }
123         Attributes attributesUpdated = attributes;
124         final Actions1 augmentation = actions.augmentation(Actions1.class);
125         if (augmentation != null && augmentation.getBgpActions() != null) {
126             final BgpActions bgpAction = augmentation.getBgpActions();
127
128             final SetAsPathPrepend asPrependAction = bgpAction.getSetAsPathPrepend();
129             final Long localPrefPrependAction = bgpAction.getSetLocalPref();
130             final BgpOriginAttrType localOriginAction = bgpAction.getSetRouteOrigin();
131             final BgpSetMedType medAction = bgpAction.getSetMed();
132             final BgpNextHopType nhAction = bgpAction.getSetNextHop();
133             final SetCommunity setCommunityAction = bgpAction.getSetCommunity();
134             final SetExtCommunity setExtCommunityAction = bgpAction.getSetExtCommunity();
135
136             if (asPrependAction != null) {
137                 attributesUpdated = this.bgpActions.get(SetAsPathPrepend.class)
138                         .applyExportAction(routeEntryInfo, routeEntryExportParameters, attributesUpdated,
139                                 asPrependAction);
140             }
141
142             if (attributesUpdated == null) {
143                 return null;
144             }
145
146             if (setCommunityAction != null) {
147                 attributesUpdated = this.bgpActions.get(SetCommunity.class)
148                         .applyExportAction(routeEntryInfo, routeEntryExportParameters, attributesUpdated,
149                                 setCommunityAction);
150             }
151
152             if (attributesUpdated == null) {
153                 return null;
154             }
155
156             if (setExtCommunityAction != null) {
157                 attributesUpdated = this.bgpActions.get(SetExtCommunity.class)
158                         .applyExportAction(routeEntryInfo, routeEntryExportParameters, attributesUpdated,
159                                 setExtCommunityAction);
160             }
161
162             boolean updated = false;
163             if (localPrefPrependAction != null || localOriginAction != null
164                     || medAction != null || nhAction != null) {
165                 updated = true;
166             }
167
168             if (updated) {
169                 final AttributesBuilder attributesUpdatedBuilder = new AttributesBuilder(attributes);
170                 if (localPrefPrependAction != null) {
171                     attributesUpdatedBuilder.setLocalPref(new LocalPrefBuilder()
172                             .setPref(localPrefPrependAction).build());
173                 }
174
175                 if (localOriginAction != null) {
176                     attributesUpdatedBuilder.setOrigin(new OriginBuilder()
177                             .setValue(BgpOrigin.forValue(localOriginAction.getIntValue())).build());
178                 }
179
180                 if (medAction != null) {
181                     attributesUpdatedBuilder.setMultiExitDisc(new MultiExitDiscBuilder()
182                             .setMed(medAction.getUint32()).build());
183                 }
184
185                 if (nhAction != null) {
186                     final IpAddress address = nhAction.getIpAddress();
187                     CNextHop nhNew;
188                     if (address != null) {
189                         if (address.getIpv4Address() != null) {
190                             nhNew = new Ipv4NextHopCaseBuilder().setIpv4NextHop(new Ipv4NextHopBuilder()
191                                     .setGlobal(address.getIpv4Address()).build()).build();
192                         } else {
193                             nhNew = new Ipv6NextHopCaseBuilder().setIpv6NextHop(new Ipv6NextHopBuilder()
194                                     .setGlobal(address.getIpv6Address()).build()).build();
195                         }
196
197                         attributesUpdatedBuilder.setCNextHop(nhNew);
198                     } else if (nhAction.getEnumeration() != null
199                             && BgpNextHopType.Enumeration.SELF == nhAction.getEnumeration()) {
200                         nhNew = new Ipv4NextHopCaseBuilder().setIpv4NextHop(new Ipv4NextHopBuilder()
201                                 .setGlobal(routeEntryInfo.getOriginatorId()).build()).build();
202                         attributesUpdatedBuilder.setCNextHop(nhNew);
203                     }
204                 }
205                 attributesUpdated = attributesUpdatedBuilder.build();
206             }
207
208             final Map<Class<? extends Augmentation<?>>, Augmentation<?>> bgpConditionsAug = BindingReflections
209                     .getAugmentations(bgpAction);
210
211             if (bgpConditionsAug != null) {
212                 for (final Map.Entry<Class<? extends Augmentation<?>>, Augmentation<?>> entry
213                         : bgpConditionsAug.entrySet()) {
214                     final BgpActionAugPolicy handler = this.bgpAugActionsRegistry.get(entry.getKey());
215                     if (handler == null) {
216                         continue;
217                     } else if (attributesUpdated == null) {
218                         return null;
219                     }
220                     attributesUpdated = handler.applyExportAction(routeEntryInfo, routeEntryExportParameters,
221                             attributesUpdated, entry.getValue());
222                 }
223             }
224         }
225
226         if (attributesUpdated == null) {
227             return null;
228         }
229
230         // Export Actions Aug
231         final Map<Class<? extends Augmentation<?>>, Augmentation<?>> conditionsAug = BindingReflections
232                 .getAugmentations(actions);
233
234         if (conditionsAug == null) {
235             return attributes;
236         }
237
238         for (final Map.Entry<Class<? extends Augmentation<?>>, Augmentation<?>> entry : conditionsAug.entrySet()) {
239             final ActionsAugPolicy handler = this.actionsRegistry.get(entry.getKey());
240             if (attributesUpdated == null) {
241                 return null;
242             } else if (handler == null) {
243                 continue;
244             }
245             attributesUpdated = handler.applyExportAction(routeEntryInfo, routeEntryExportParameters,
246                     attributesUpdated, (Augmentation<Actions>) entry.getValue());
247         }
248
249         return attributesUpdated;
250     }
251
252     @SuppressWarnings("unchecked")
253     Attributes applyImportAction(
254             final RouteEntryBaseAttributes routeEntryInfo,
255             final BGPRouteEntryImportParameters routeParameters,
256             final Attributes attributes,
257             final Actions actions) {
258         if (actions.getRouteDisposition() instanceof RejectRoute) {
259             return null;
260         }
261         Attributes attributesUpdated = attributes;
262         final Actions1 augmentation = actions.augmentation(Actions1.class);
263
264         if (augmentation != null && augmentation.getBgpActions() != null) {
265             final BgpActions bgpAction = augmentation.getBgpActions();
266             final SetCommunity setCommunityAction = bgpAction.getSetCommunity();
267             final SetExtCommunity setExtCommunityAction = bgpAction.getSetExtCommunity();
268             final SetAsPathPrepend asPrependAction = bgpAction.getSetAsPathPrepend();
269
270             if (asPrependAction != null) {
271                 attributesUpdated = this.bgpActions.get(asPrependAction.getClass())
272                         .applyImportAction(routeEntryInfo, routeParameters, attributesUpdated, asPrependAction);
273             }
274
275             if (attributesUpdated == null) {
276                 return null;
277             }
278
279             if (setCommunityAction != null) {
280                 attributesUpdated = this.bgpActions.get(SetCommunity.class)
281                         .applyImportAction(routeEntryInfo, routeParameters, attributesUpdated,
282                                 setCommunityAction);
283             }
284
285             if (attributesUpdated == null) {
286                 return null;
287             }
288
289             if (setExtCommunityAction != null) {
290                 attributesUpdated = this.bgpActions.get(SetExtCommunity.class)
291                         .applyImportAction(routeEntryInfo, routeParameters, attributesUpdated, setExtCommunityAction);
292             }
293
294             if (attributesUpdated == null) {
295                 return null;
296             }
297
298             final Map<Class<? extends Augmentation<?>>, Augmentation<?>> bgpConditionsAug = BindingReflections
299                     .getAugmentations(bgpAction);
300
301             if (bgpConditionsAug == null) {
302                 return attributes;
303             }
304
305             for (final Map.Entry<Class<? extends Augmentation<?>>, Augmentation<?>> entry
306                     : bgpConditionsAug.entrySet()) {
307                 final BgpActionAugPolicy handler = this.bgpAugActionsRegistry.get(entry.getKey());
308                 if (handler == null) {
309                     continue;
310                 } else if (attributesUpdated == null) {
311                     return null;
312                 }
313                 attributesUpdated = handler.applyImportAction(routeEntryInfo, routeParameters, attributesUpdated,
314                         entry.getValue());
315             }
316             if (attributesUpdated == null) {
317                 return null;
318             }
319         }
320         // Augmented Actions
321         final Map<Class<? extends Augmentation<?>>, Augmentation<?>> conditionsAug = BindingReflections
322                 .getAugmentations(actions);
323
324         if (conditionsAug == null) {
325             return attributesUpdated;
326         }
327         for (final Map.Entry<Class<? extends Augmentation<?>>, Augmentation<?>> entry : conditionsAug.entrySet()) {
328             final ActionsAugPolicy handler = this.actionsRegistry.get(entry.getKey());
329             if (handler == null) {
330                 continue;
331             } else if (attributesUpdated == null) {
332                 return null;
333             }
334             attributesUpdated = handler.applyImportAction(routeEntryInfo, routeParameters, attributesUpdated,
335                     (Augmentation<Actions>) entry.getValue());
336         }
337         return attributesUpdated;
338     }
339 }