OpenConfig BGP more defensive
[bgpcep.git] / bgp / openconfig-impl / src / main / java / org / opendaylight / protocol / bgp / openconfig / impl / moduleconfig / BGPOpenConfigListener.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  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.impl.moduleconfig;
10
11 import com.google.common.base.Preconditions;
12 import java.util.Collection;
13 import java.util.List;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.DataObjectModification;
16 import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
17 import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier;
18 import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
19 import org.opendaylight.controller.md.sal.binding.api.MountPoint;
20 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
21 import org.opendaylight.protocol.bgp.openconfig.impl.spi.BGPConfigStateStore;
22 import org.opendaylight.protocol.bgp.openconfig.impl.util.OpenConfigUtil;
23 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.neighbors.Neighbor;
24 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.Bgp;
25 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.bgp.Global;
26 import org.opendaylight.yang.gen.v1.http.openconfig.net.yang.bgp.rev151009.bgp.top.bgp.Neighbors;
27 import org.opendaylight.yangtools.concepts.ListenerRegistration;
28 import org.opendaylight.yangtools.yang.binding.DataObject;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 public final class BGPOpenConfigListener implements DataTreeChangeListener<Bgp>, AutoCloseable {
33
34     private static final Logger LOG = LoggerFactory.getLogger(BGPOpenConfigListener.class);
35
36     private final ListenerRegistration<BGPOpenConfigListener> registerDataTreeChangeListener;
37     private final BGPRibImplProvider ribImplProvider;
38     private final BGPPeerProvider peerProvider;
39     private final BGPAppPeerProvider appPeerProvider;
40
41     public BGPOpenConfigListener(final DataBroker dataBroker, final MountPoint mountPoint, final BGPConfigStateStore configStateHolders) {
42         final DataBroker mpDataBroker = Preconditions.checkNotNull(mountPoint).getService(DataBroker.class).get();
43         final BGPConfigModuleProvider configModuleWriter = new BGPConfigModuleProvider();
44         this.ribImplProvider = new BGPRibImplProvider(configStateHolders, configModuleWriter, mpDataBroker);
45         this.peerProvider = new BGPPeerProvider(configStateHolders, configModuleWriter, mpDataBroker);
46         this.appPeerProvider = new BGPAppPeerProvider(configStateHolders, configModuleWriter, mpDataBroker);
47         this.registerDataTreeChangeListener = dataBroker.registerDataTreeChangeListener(
48                 new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, OpenConfigUtil.BGP_IID), this);
49     }
50
51     @Override
52     public void onDataTreeChanged(final Collection<DataTreeModification<Bgp>> changes) {
53         for (final DataTreeModification<Bgp> dataTreeModification : changes) {
54             final DataObjectModification<Bgp> rootNode = dataTreeModification.getRootNode();
55             for (final DataObjectModification<? extends DataObject> dataObjectModification : rootNode.getModifiedChildren()) {
56                 switch (dataObjectModification.getModificationType()) {
57                 case DELETE:
58                     onOpenConfigRemoved(dataObjectModification.getDataBefore());
59                     break;
60                 case SUBTREE_MODIFIED:
61                 case WRITE:
62                     onOpenConfigModified(dataObjectModification);
63                     break;
64                 default:
65                     throw new IllegalArgumentException("Unhandled modification type " + rootNode.getModificationType());
66                 }
67             }
68         }
69     }
70
71     @Override
72     public void close() {
73         registerDataTreeChangeListener.close();
74     }
75
76     private void onOpenConfigRemoved(final DataObject removedData) {
77         if (removedData instanceof Global) {
78             ribImplProvider.onGlobalRemoved((Global) removedData);
79         } else if (removedData instanceof Neighbors) {
80             final List<Neighbor> neighbors = ((Neighbors) removedData).getNeighbor();
81             if( neighbors != null) {
82                 for (final Neighbor neighbor : neighbors) {
83                     removeNeighbor(neighbor);
84                 }
85             }
86         } else {
87             LOG.info("Skipping unhandled removed data: {}", removedData);
88         }
89     }
90
91     private void onOpenConfigModified(final DataObjectModification<? extends DataObject> dataObjectModification) {
92         final DataObject modifiedData = dataObjectModification.getDataAfter();
93         if (modifiedData instanceof Global) {
94             ribImplProvider.onGlobalModified((Global) modifiedData);
95         } else if (modifiedData instanceof Neighbors) {
96             for (final DataObjectModification<? extends DataObject> childModification : dataObjectModification.getModifiedChildren()) {
97                 switch (childModification.getModificationType()) {
98                 case DELETE:
99                     final Neighbor before = (Neighbor) childModification.getDataBefore();
100                     removeNeighbor(before);
101                     break;
102                 case SUBTREE_MODIFIED:
103                 case WRITE:
104                     final Neighbor after = (Neighbor) childModification.getDataAfter();
105                     modifyNeighbor(after);
106                     break;
107                 default:
108                     break;
109                 }
110             }
111         } else {
112             LOG.info("Skipping unhandled modified data: {}", modifiedData);
113         }
114     }
115
116     private void removeNeighbor(final Neighbor neighbor) {
117         if (OpenConfigUtil.isAppNeighbor(neighbor)) {
118             appPeerProvider.onNeighborRemoved(neighbor);
119         } else {
120             peerProvider.onNeighborRemoved(neighbor);
121         }
122     }
123
124     private void modifyNeighbor(final Neighbor neighbor) {
125         if (OpenConfigUtil.isAppNeighbor(neighbor)) {
126             appPeerProvider.onNeighborModified(neighbor);
127         } else {
128             peerProvider.onNeighborModified(neighbor);
129         }
130     }
131 }