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