ebd49642ceaf58c54f6657bfeb57fb1108b27a35
[vpnservice.git] / bgpmanager / bgpmanager-impl / src / main / java / org / opendaylight / bgpmanager / BgpConfigurationManager.java
1 /*
2  * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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 package org.opendaylight.bgpmanager;
9
10 import java.util.Collections;
11 import java.util.Map;
12 import java.util.Set;
13
14 import org.apache.thrift.TException;
15 import org.opendaylight.bgpmanager.globals.BgpConfiguration;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
21 import org.opendaylight.yangtools.concepts.ListenerRegistration;
22 import org.opendaylight.yangtools.yang.binding.DataObject;
23 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
24 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.bgp.rev130715.BgpRouter;
25 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.bgp.rev130715.BgpNeighbors;
26 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.bgp.rev130715.bgp.neighbors.BgpNeighbor;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 import java.util.List;
32
33 import com.google.common.base.Optional;
34 import com.google.common.base.Preconditions;
35
36 public class BgpConfigurationManager {
37     private static final Logger LOG = LoggerFactory.getLogger(BgpConfigurationManager.class);
38     private ListenerRegistration<DataChangeListener> listenerRegistration;
39     private BgpConfiguration bgpConfiguration;
40     private BgpManager bgpManager;
41     private final DataBroker broker;
42     private static final int MAX_RETRIES_BGP_COMMUNICATION = 1;
43     private enum BgpOp {
44         START_BGP, ADD_NGHBR, DEL_NGHBR
45     }
46
47     public BgpConfigurationManager(final DataBroker db, BgpConfiguration bgpCfg, BgpManager bgpMgr) {
48         broker = db;
49         bgpConfiguration = bgpCfg;
50         bgpManager = bgpMgr;
51         BgpRtrCfgManager rtrCfgManager = new BgpRtrCfgManager(broker);
52         BgpNghbrCfgManager nghbrCfgManager = new BgpNghbrCfgManager(broker);
53     }
54
55     public class BgpRtrCfgManager extends AbstractDataChangeListener<BgpRouter> implements AutoCloseable {
56
57         public BgpRtrCfgManager(final DataBroker db) {
58             super(BgpRouter.class);
59             registerListener(db);
60         }
61
62         private void registerListener(final DataBroker db) {
63             try {
64                 listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
65                     getWildCardPath(), BgpRtrCfgManager.this, DataChangeScope.SUBTREE);
66             } catch (final Exception e) {
67                 LOG.error("BGP Configuration DataChange listener registration fail!", e);
68                 throw new IllegalStateException("BGP Configuration registration Listener failed.", e);
69             }
70         }
71
72         private synchronized void removeBgpRouter(BgpRouter del)
73         {
74             bgpManager.disconnect();
75
76             bgpConfiguration.setRouterId("");
77             bgpConfiguration.setAsNum(0);
78
79         }
80
81         @Override
82         protected void remove(InstanceIdentifier<BgpRouter> identifier,
83                               BgpRouter del) {
84
85             LOG.debug("Bgp Router deleted in DS - key: {} value={} ", identifier, del);
86
87             removeBgpRouter(del);
88
89         }
90
91         private synchronized void updateBgpRouter(BgpRouter original, BgpRouter update)
92         {
93             if(bgpConfiguration.getAsNum() != update.getLocalAsNumber()) {
94                 bgpConfiguration.setAsNum(update.getLocalAsNumber());
95                 bgpConfiguration.setConfigUpdated();
96             }
97             if(bgpConfiguration.getRouterId() != update.getLocalAsIdentifier().getIpv4Address().getValue()) {
98                 bgpConfiguration.setRouterId(update.getLocalAsIdentifier().getIpv4Address().getValue());
99                 bgpConfiguration.setConfigUpdated();
100             }
101
102             if(bgpConfiguration.isConfigUpdated()) {
103                 configureBgpServer(BgpOp.START_BGP);
104                 bgpConfiguration.unsetConfigUpdated();
105             }
106
107         }
108
109         @Override
110         protected void update(InstanceIdentifier<BgpRouter> identifier,
111                               BgpRouter original, BgpRouter update) {
112
113             LOG.debug("Bgp Router Updated in DS - key: {}, original={}, update={} ", identifier, original, update);
114
115             updateBgpRouter(original, update);
116         }
117
118         private synchronized void addBgpRouter(BgpRouter value){
119             if(value.getLocalAsNumber() != null) {
120                 bgpConfiguration.setAsNum(value.getLocalAsNumber());
121             }
122             if(value.getLocalAsIdentifier() != null) {
123                 bgpConfiguration.setRouterId(value.getLocalAsIdentifier().getIpv4Address().getValue());
124             }
125
126             if(value.getLocalAsNumber() == null || value.getLocalAsIdentifier() == null)
127                 return;
128
129             configureBgpServer(BgpOp.START_BGP);
130         }
131
132         @Override
133         protected void add(InstanceIdentifier<BgpRouter> identifier,
134                            BgpRouter value) {
135             LOG.debug("Bgp Router added in DS - key: {}, value={} ",identifier, value);
136
137             addBgpRouter(value);
138         }
139
140         private InstanceIdentifier<BgpRouter> getWildCardPath() {
141             return InstanceIdentifier.create(BgpRouter.class);
142         }
143
144         @Override
145         public void close() throws Exception {
146             if (listenerRegistration != null) {
147                 try {
148                     listenerRegistration.close();
149                 } catch (final Exception e) {
150                     LOG.error("Error when cleaning up DataChangeListener.", e);
151                 }
152                 listenerRegistration = null;
153             }
154             LOG.info("Bgp Router Manager Closed");
155         }
156
157     }
158     public class BgpNghbrCfgManager extends AbstractDataChangeListener<BgpNeighbors> implements AutoCloseable {
159
160         public BgpNghbrCfgManager(final DataBroker db) {
161             super(BgpNeighbors.class);
162             registerListener(db);
163         }
164
165         private void registerListener(final DataBroker db) {
166             try {
167                 listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
168                     getWildCardPath(), BgpNghbrCfgManager.this, DataChangeScope.SUBTREE);
169             } catch (final Exception e) {
170                 LOG.error("BGP Neighbor DataChange listener registration fail!", e);
171                 throw new IllegalStateException("BGP Neighbor registration Listener failed.", e);
172             }
173         }
174
175         private synchronized void removeBgpNeighbors(BgpNeighbors del) {
176             List<BgpNeighbor> bgpNeighborList = del.getBgpNeighbor();
177             BgpNeighbor gateway = bgpNeighborList.get(0);
178
179             if(gateway != null) {
180                 if ((gateway.getPeerAddressType() != null) && (gateway.getPeerAddressType() instanceof org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.bgp.rev130715.bgp.neighbors.bgp.neighbor.peer.address.type.IpAddress)) {
181                     IpAddress neighborIPAddr = ((org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.bgp.rev130715.bgp.neighbors.bgp.neighbor.peer.address.type.IpAddress) gateway.getPeerAddressType()).getIpAddress();
182                     LOG.debug("Bgp Neighbor IP Address {} ", neighborIPAddr.getIpv4Address().getValue());
183
184                     configureBgpServer(BgpOp.DEL_NGHBR);
185
186                     bgpConfiguration.setNeighbourIp("");
187                     bgpConfiguration.setNeighbourAsNum(0);
188
189                 }
190             }
191
192         }
193
194         @Override
195         protected void remove(InstanceIdentifier<BgpNeighbors> identifier,
196                               BgpNeighbors del) {
197
198             LOG.debug("Bgp Neighbors deleted in DS - key: {}, value={} ", identifier, del);
199             removeBgpNeighbors(del);
200         }
201
202         private synchronized void updateBgpNeighbors(BgpNeighbors original, BgpNeighbors update) {
203
204             List<BgpNeighbor> bgpNeighborList = update.getBgpNeighbor();
205
206             //handle the case where there are no neighbors configured - single neighbor entry has been deleted
207             if(bgpNeighborList.isEmpty()) {
208                 configureBgpServer(BgpOp.DEL_NGHBR);
209                 return;
210             }
211
212             //We will always consider the first element of this list, since there can be just one DC Gateway
213             BgpNeighbor gateway = bgpNeighborList.get(0);
214
215             if(gateway != null) {
216                 if(gateway.getAsNumber() != null ||
217                     ((gateway.getPeerAddressType() != null) && (gateway.getPeerAddressType() instanceof org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.bgp.rev130715.bgp.neighbors.bgp.neighbor.peer.address.type.IpAddress))) {
218                     //there is an updated neighbor, so we need to delete the old neighbor
219                     configureBgpServer(BgpOp.DEL_NGHBR);
220                 }
221                 if(gateway.getAsNumber() != null) {
222                     LOG.debug("Bgp Neighbor AS number {} ", gateway.getAsNumber());
223                     if(bgpConfiguration.getNeighbourAsNum() != gateway.getAsNumber()) {
224                         bgpConfiguration.setNeighbourAsNum(gateway.getAsNumber());
225                         bgpConfiguration.setConfigUpdated();
226                     }
227                 }
228                 if((gateway.getPeerAddressType() != null) && (gateway.getPeerAddressType() instanceof org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.bgp.rev130715.bgp.neighbors.bgp.neighbor.peer.address.type.IpAddress)) {
229                     IpAddress neighborIPAddr = ((org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.bgp.rev130715.bgp.neighbors.bgp.neighbor.peer.address.type.IpAddress)gateway.getPeerAddressType()).getIpAddress();
230                     LOG.debug("Bgp Neighbor IP Address {}", neighborIPAddr.getIpv4Address().getValue());
231                     if(bgpConfiguration.getNeighbourIp() != neighborIPAddr.getIpv4Address().getValue()) {
232                         bgpConfiguration.setNeighbourIp(neighborIPAddr.getIpv4Address().getValue());
233                         bgpConfiguration.setConfigUpdated();
234                     }
235
236                 }
237             }
238             if(bgpConfiguration.isConfigUpdated()) {
239                 //add the newly configured neighbor
240                 configureBgpServer(BgpOp.ADD_NGHBR);
241             }
242         }
243
244         @Override
245         protected void update(InstanceIdentifier<BgpNeighbors> identifier,
246                               BgpNeighbors original, BgpNeighbors update) {
247
248             LOG.debug("Bgp Neighbors Updated in DS - key: {}, original={}, update={} ", identifier,  original, update);
249
250             updateBgpNeighbors(original, update);
251
252         }
253
254         private synchronized void addBgpNeighbors(BgpNeighbors value) {
255             List<BgpNeighbor> bgpNeighborList = value.getBgpNeighbor();
256
257             //We will always consider the first element of this list, since there can be just one DC Gateway
258             BgpNeighbor gateway = bgpNeighborList.get(0);
259
260             if(gateway != null) {
261                 if(gateway.getAsNumber() != null) {
262                     LOG.debug("Bgp Neighbor AS number {} ", gateway.getAsNumber());
263                     bgpConfiguration.setNeighbourAsNum(gateway.getAsNumber());
264                 }
265                 if((gateway.getPeerAddressType() != null) && (gateway.getPeerAddressType() instanceof org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.bgp.rev130715.bgp.neighbors.bgp.neighbor.peer.address.type.IpAddress)) {
266                     IpAddress neighborIPAddr = ((org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.bgp.rev130715.bgp.neighbors.bgp.neighbor.peer.address.type.IpAddress)gateway.getPeerAddressType()).getIpAddress();
267                     LOG.debug("Bgp Neighbor IP Address {} ", neighborIPAddr.getIpv4Address().getValue());
268                     bgpConfiguration.setNeighbourIp(neighborIPAddr.getIpv4Address().getValue());
269
270                 }
271                 if(bgpConfiguration.getNeighbourAsNum() != 0  && bgpConfiguration.getNeighbourIp() != null) {
272                     configureBgpServer(BgpOp.ADD_NGHBR);
273                 }
274             }
275
276         }
277
278         @Override
279         protected void add(InstanceIdentifier<BgpNeighbors> identifier,
280                            BgpNeighbors value) {
281             LOG.debug("Bgp Neighbor added in DS - key: {}, value={} ", identifier, value);
282
283             addBgpNeighbors(value);
284         }
285
286         private InstanceIdentifier<?> getWildCardPath() {
287             return InstanceIdentifier.create(BgpNeighbors.class);
288         }
289
290
291         @Override
292         public void close() throws Exception {
293             if (listenerRegistration != null) {
294                 try {
295                     listenerRegistration.close();
296                 } catch (final Exception e) {
297                     LOG.error("Error when cleaning up DataChangeListener.", e);
298                 }
299                 listenerRegistration = null;
300             }
301             LOG.info("Bgp Neighbor Manager Closed");
302         }
303
304     }
305
306     private void configureBgpServer(BgpOp bgpOp) {
307         int retryCount = 0;
308         boolean retry = false;
309         do {
310             try {
311                 switch(bgpOp) {
312                     case START_BGP:
313                         bgpManager.startBgpService();
314                         break;
315                     case ADD_NGHBR:
316                         bgpManager.addNeighbor(bgpConfiguration.getNeighbourIp(), bgpConfiguration.getNeighbourAsNum());
317                         break;
318                     case DEL_NGHBR:
319                         bgpManager.deleteNeighbor(bgpConfiguration.getNeighbourIp());
320                         break;
321                     default:
322                         LOG.error("Invalid configuration option {}", bgpOp);
323                 }
324
325                 retry = false;
326             } catch (TException t) {
327                 retry = true;
328                 retryCount++;
329             }
330         } while(retry && retryCount <= MAX_RETRIES_BGP_COMMUNICATION);
331     }
332 }