2 * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. and others. 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.bgpmanager;
11 import java.net.SocketTimeoutException;
13 import java.util.concurrent.ConcurrentMap;
14 import java.util.concurrent.CountDownLatch;
16 import org.apache.thrift.TException;
17 import org.opendaylight.bgpmanager.thrift.client.globals.Route;
18 import org.opendaylight.bgpmanager.thrift.client.implementation.BgpRouter;
19 import org.opendaylight.bgpmanager.thrift.server.implementation.BgpThriftService;
20 import org.opendaylight.bgpmanager.thrift.exceptions.BgpRouterException;
21 import org.opendaylight.bgpmanager.api.IBgpManager;
22 import org.opendaylight.bgpmanager.globals.BgpConfiguration;
23 import org.opendaylight.bgpmanager.globals.BgpConstants;
25 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
26 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
27 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
28 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
30 import org.osgi.framework.Bundle;
31 import org.osgi.framework.BundleContext;
32 import org.osgi.framework.FrameworkUtil;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
36 public class BgpManager implements BindingAwareProvider, AutoCloseable, IBgpManager {
38 private static final Logger s_logger = LoggerFactory.getLogger(BgpManager.class);
39 private BgpConfigurationManager bgpConfigurationMgr;
40 private FibDSWriter fibDSWriter;
41 private BgpConfiguration bgpConfiguration = new BgpConfiguration();
42 private BgpRouter bgpThriftClient;
43 private BgpThriftService bgpThriftService;
44 private boolean isBgpInitialized = false;
45 private boolean hasBgpServiceStarted = false;
46 private String bgpHost;
50 private String getCustomConfig(String var, String def) {
51 Bundle b = FrameworkUtil.getBundle(this.getClass());
52 BundleContext context = null;
54 context = b.getBundleContext();
57 return context.getProperty(var);
63 private void initializeBGPCommunication() {
64 //start our side of thrift server
65 bgpThriftService = new BgpThriftService(this, fibDSWriter);
66 bgpThriftService.start();
68 //start bgp thrift client connection
69 bgpThriftClient = new BgpRouter();
71 bgpHost = getCustomConfig(BgpConstants.BGP_SPEAKER_HOST_NAME, BgpConstants.DEFAULT_BGP_HOST_NAME);
72 bgpPort = BgpConstants.DEFAULT_BGP_THRIFT_PORT;
74 configureBgpServer(bgpHost, bgpPort);
76 connectToServer(bgpHost, bgpPort);
77 } catch (Exception e) {
81 isBgpInitialized = true;
82 //notify(); //notify all threads waiting for bgp init
86 public synchronized void waitForBgpInit() {
87 if(!isBgpInitialized) {
90 } catch (InterruptedException e) {
91 s_logger.error("InterruptedException while waiting for Bgp connection to initialize");
97 public void startBgpService() throws TException {
98 if(bgpThriftClient == null) {
99 s_logger.info("Start Bgp Service - bgpThriftClient is null. Unable to start BGP service.");
103 // Now try start bgp - if bgp is already Active, it will tell us, nothing to do then
105 bgpThriftClient.startBgp((int)bgpConfiguration.getAsNum(), bgpConfiguration.getRouterId());
106 s_logger.info("Started BGP with AS number " + (int)bgpConfiguration.getAsNum() + " and router id " + bgpConfiguration.getRouterId());
107 } catch (BgpRouterException be) {
108 if(be.getErrorCode() == BgpRouterException.BGP_ERR_ACTIVE) {
109 s_logger.info("bgp server already active");
112 else if(be.getErrorCode() == BgpRouterException.BGP_ERR_NOT_INITED) {
113 s_logger.error("bgp server connection not initialized.");
118 s_logger.error("application error while starting bgp server " + be.getErrorCode());
122 } catch (TException t) {
123 //s_logger.error("Transport error while starting bgp server ", t);
124 s_logger.error("Could not set up thrift connection with bgp server");
127 } catch (Exception e) {
128 s_logger.error("Error while starting bgp server", e);
132 hasBgpServiceStarted = true;
137 public void onSessionInitiated(ProviderContext session) {
138 s_logger.info("BgpManager Session Initiated");
140 final DataBroker dataBroker = session.getSALService(DataBroker.class);
141 bgpConfigurationMgr = new BgpConfigurationManager(dataBroker, bgpConfiguration, this);
142 fibDSWriter = new FibDSWriter(dataBroker);
143 } catch (Exception e) {
144 s_logger.error("Error initializing services", e);
147 initializeBGPCommunication();
152 public void close() throws Exception {
153 s_logger.info("BgpManager Closed");
155 //close the client and server ends of the thrift communication
156 if(bgpThriftClient != null)
157 bgpThriftClient.disconnect();
158 bgpThriftService.stop();
163 private void setBgpServerDetails() {
164 if(bgpThriftClient != null)
165 bgpThriftClient.setBgpServer(bgpHost, bgpPort);
168 private void configureBgpServer(String bgpServer, int bgpPort) {
169 bgpConfiguration.setBgpServer(bgpServer);
170 bgpConfiguration.setBgpPort(bgpPort);
171 setBgpServerDetails();
174 protected void addNeighbor(String ipAddress, long asNum) throws TException {
175 if(bgpThriftClient == null) {
176 s_logger.info("Add BGP Neighbor - bgpThriftClient is null. Unable to add BGP Neighbor.");
181 bgpThriftClient.addNeighbor(ipAddress, (int) asNum);
182 } catch (BgpRouterException b) {
183 s_logger.error("Failed to add BGP neighbor " + ipAddress + "due to BgpRouter Exception number " + b.getErrorCode());
184 s_logger.error("BgpRouterException trace ", b);
185 } catch (TException t) {
186 s_logger.error(String.format("Failed adding neighbor %s due to Transport error", ipAddress));
189 } catch (Exception e) {
190 s_logger.error(String.format("Failed adding neighbor %s", ipAddress));
195 protected void deleteNeighbor(String ipAddress) throws TException {
196 if(bgpThriftClient == null) {
197 s_logger.info("Delete BGP Neighbor - bgpThriftClient is null. Unable to delete BGP Neighbor.");
202 bgpThriftClient.delNeighbor(ipAddress);
203 } catch (BgpRouterException b) {
204 s_logger.error("Failed to delete BGP neighbor " + ipAddress + "due to BgpRouter Exception number " + b.getErrorCode());
205 s_logger.error("BgpRouterException trace ", b);
206 }catch (TException t) {
207 s_logger.error(String.format("Failed deleting neighbor %s due to Transport error", ipAddress));
210 } catch (Exception e) {
211 s_logger.error(String.format("Failed deleting neighbor %s", ipAddress));
217 public void addVrf(String rd, Collection<String> importRts, Collection<String> exportRts) throws Exception {
218 if(bgpThriftClient == null) {
219 s_logger.info("Add BGP vrf - bgpThriftClient is null. Unable to add BGP vrf.");
223 bgpThriftClient.addVrf(rd, new ArrayList<>(importRts), new ArrayList<>(exportRts));
224 } catch (BgpRouterException b) {
225 s_logger.error("Failed to add BGP vrf " + rd + "due to BgpRouter Exception number " + b.getErrorCode());
226 s_logger.error("BgpRouterException trace ", b);
228 } catch (TException t) {
229 s_logger.error(String.format("Failed adding vrf %s due to Transport error", rd));
232 } catch (Exception e) {
233 s_logger.error(String.format("Failed adding vrf %s", rd));
239 public void deleteVrf(String rd) throws Exception {
240 if(bgpThriftClient == null) {
241 s_logger.info("Delete BGP vrf - bgpThriftClient is null. Unable to delete BGP vrf.");
245 bgpThriftClient.delVrf(rd);
246 } catch (BgpRouterException b) {
247 s_logger.error("Failed to delete BGP vrf " + rd + "due to BgpRouter Exception number " + b.getErrorCode());
248 s_logger.error("BgpRouterException trace ", b);
250 } catch (TException t) {
251 s_logger.error(String.format("Failed deleting vrf %s due to Transport error", rd));
254 } catch (Exception e) {
255 s_logger.error(String.format("Failed deleting vrf %s", rd));
261 public void addPrefix(String rd, String prefix, String nextHop, int vpnLabel) throws Exception {
262 if(bgpThriftClient == null) {
263 s_logger.info("Add BGP prefix - bgpThriftClient is null. Unable to add BGP prefix.");
266 if(!hasBgpServiceStarted) {
267 fibDSWriter.addFibEntryToDS(rd, prefix, nextHop, vpnLabel);
270 bgpThriftClient.addPrefix(rd, prefix, nextHop, vpnLabel);
271 } catch (BgpRouterException b) {
272 s_logger.error("Failed to add BGP prefix " + prefix + "due to BgpRouter Exception number " + b.getErrorCode());
273 s_logger.error("BgpRouterException trace ", b);
275 } catch (TException t) {
276 s_logger.error(String.format("Failed adding prefix entry <vrf:prefix:nexthop:vpnlabel> %s:%s:%s:%d due to Transport error",
277 rd, prefix, nextHop, vpnLabel));
280 } catch (Exception e) {
281 s_logger.error(String.format("Failed adding prefix entry <vrf:prefix:nexthop:vpnlabel> %s:%s:%s:%d",
282 rd, prefix, nextHop, vpnLabel));
289 public void deletePrefix(String rd, String prefix) throws Exception {
290 if(bgpThriftClient == null) {
291 s_logger.info("Delete BGP prefix - bgpThriftClient is null. Unable to delete BGP prefix.");
294 if(!hasBgpServiceStarted) {
295 fibDSWriter.removeFibEntryFromDS(rd, prefix);
298 bgpThriftClient.delPrefix(rd, prefix);
299 } catch (BgpRouterException b) {
300 s_logger.error("Failed to delete BGP prefix " + prefix + "due to BgpRouter Exception number " + b.getErrorCode());
301 s_logger.error("BgpRouterException trace ", b);
303 } catch (TException t) {
304 s_logger.error(String.format("Failed deleting prefix entry <vrf:prefix> %s:%s due to Transport error",
308 } catch (Exception e) {
309 s_logger.error(String.format("Failed deleting prefix entry <vrf:prefix> %s:%s",
315 private void connectToServer(String host, int port) throws Exception {
320 if(bgpThriftClient == null) {
321 s_logger.error("Failed to connect to BGP server since Bgp Thrift Client is not initialized yet.");
325 bgpThriftClient.connect(host, port);
326 s_logger.info("Connected to BGP server " + host + " on port " + port);
327 } catch (BgpRouterException b) {
328 s_logger.error("Failed to connect to BGP server " + host + " on port " + port + " due to BgpRouter Exception number " + b.getErrorCode());
329 s_logger.error("BgpRouterException trace ", b);
331 } catch (TException t) {
332 s_logger.error("Failed to initialize BGP Connection due to Transport error ", t);
335 catch (Exception e) {
336 s_logger.error("Failed to initialize BGP Connection ", e);
341 public void configureBgp(long asNum, String routerId) {
343 bgpConfiguration.setAsNum(asNum);
344 bgpConfiguration.setRouterId(routerId);
345 } catch(Throwable e) {
346 s_logger.error("failed configuring bgp ",e);
350 public synchronized void reInitConn() {
353 bgpThriftClient.reInit();
354 s_logger.info("Reinitialized connection to BGP Server " + bgpHost);
355 } catch (BgpRouterException b) {
356 s_logger.error("Failed to reinitialize connection to BGP server " + bgpHost + " on port " + bgpPort + " due to BgpRouter Exception number " + b.getErrorCode());
357 s_logger.error("BgpRouterException trace ", b);
358 } catch (TException t) {
359 s_logger.error("Failed to reinitialize BGP Connection due to Transport error.");
361 catch (Exception e) {
362 s_logger.error("Failed to reinitialize BGP Connection.", e);
366 /*public synchronized void startBgpSync() {
367 boolean getRoutes = true;
368 readBgpConfiguration();
370 pushConfigurationToBgp();
372 } catch (BgpRouterException b) {
373 s_logger.error("Failed to push configuration to BGP due to BgpRouter Exception number " + b.getErrorCode());
374 s_logger.error("BgpRouterException trace ", b);
375 if(b.getErrorCode() == BgpRouterException.BGP_ERR_INACTIVE)
377 } catch (Exception e) {
378 s_logger.error("Failed to push configuration to bgp ", e);
380 if(getRoutes == true)
381 pullConfigurationFromBgp();
382 //controllerResyncLatch.countDown();
385 /*public void waitForControllerBgpResync() {
387 controllerResyncLatch.await();
388 } catch (InterruptedException e) {
392 /*private void pullConfigurationFromBgp() {
393 //get routes from bgp server
394 s_logger.info("Starting bgp route sync");
396 bgpThriftClient.doRouteSync();
397 } catch (BgpRouterException b) {
398 s_logger.error("Failed BGP Route sync due to BgpRouter Exception number " + b.getErrorCode());
399 s_logger.error("BgpRouterException trace ", b);
400 } catch (Exception e) {
401 s_logger.error("Failed to pull configuration from bgp ", e);
405 /*private BgpConfiguration readBgpConfiguration() {
407 bgpConfiguration = cache.get("bgpConfiguration");
408 if (bgpConfiguration == null) {
409 s_logger.info("Created bgp configuration cache");
410 bgpConfiguration = new BgpConfiguration();
411 cache.put("bgpConfiguration", bgpConfiguration);
413 s_logger.info("Using bgp configuration cache");
416 return bgpConfiguration;
419 /*public synchronized void pushConfigurationToBgp() throws Exception {
420 if (bgpConfiguration.getAsNum() == 0) {
421 s_logger.error("No as num configured, Skipping the push configuration to bgp ");
422 throw new BgpRouterException(BgpRouterException.BGP_ERR_INACTIVE);
425 if(bgpThriftClient == null) {
426 s_logger.error("bgpThriftClient is null. Skipping the push configuration to bgp.");
427 throw new BgpRouterException(BgpRouterException.BGP_ERR_INACTIVE);
432 bgpThriftClient.startBgp((int)bgpConfiguration.getAsNum(), bgpConfiguration.getRouterId());
433 s_logger.info("Started BGP with AS number " + (int)bgpConfiguration.getAsNum() + " and router id " + bgpConfiguration.getRouterId());
434 } catch (BgpRouterException be) {
435 if(be.getErrorCode() == BgpRouterException.BGP_ERR_ACTIVE) {
436 s_logger.info("bgp server already active");
437 return; //the assumption here is that bgp server is configured already with neighbor, vrfs and routes as well
438 } if(be.getErrorCode() == BgpRouterException.BGP_ERR_INACTIVE) {
439 s_logger.info("bgp server inactive");
444 s_logger.error("application error while starting bgp server %d", be.getErrorCode());
448 } catch (SocketTimeoutException to) {
449 s_logger.error("Socket Timeout error while starting bgp server", to);
451 } catch (TException t) {
452 s_logger.error("Transport error while starting bgp server ", t);
454 } catch (Exception e) {
455 s_logger.error("Error while starting bgp server", e);
458 if (bgpConfiguration.getNeighbourIp().trim().length() > 0) {
460 bgpThriftClient.addNeighbor(bgpConfiguration.getNeighbourIp(), bgpConfiguration.getNeighbourAsNum());
461 } catch (TException t) {
462 s_logger.error("Failed to push vrf to bgp due to Transport error" );
465 addNeighbor(bgpConfiguration.getNeighbourIp(), bgpConfiguration.getNeighbourAsNum());
466 } catch (Exception e) {
467 s_logger.error("Error while starting bgp server", e);
473 tenant = tenantManager.getTenant("NEUTRON");
474 } catch (TenantNotFoundException e) {
475 s_logger.error("Tenant not found. Skipping push configuration to bgp.");
478 if (tenant != null) {
479 int tenantId = tenant.getTenantId();
481 Set<VpnInstanceInfo> vpnInfos = l3Manager.getVpnInstanceManager().getVpnsForTenant(tenantId);
482 s_logger.info("Number of vpns to configure is "+vpnInfos.size());
483 for (VpnInstanceInfo vpnInfo: vpnInfos) {
485 bgpThriftClient.addVrf(vpnInfo.getRouteDistinguisher(),
486 new ArrayList<>(vpnInfo.getRtImportList()),
487 new ArrayList<>(vpnInfo.getRtExportList()));
488 } catch (TException t) {
489 s_logger.error("Failed to push vrf to bgp due to Transport error" );
492 addVrf(vpnInfo.getRouteDistinguisher(), new ArrayList<>(vpnInfo.getRtImportList()),
493 new ArrayList<>(vpnInfo.getRtExportList()));
494 } catch (Exception e) {
495 s_logger.error("Failed to push vrf to bgp ", e);
498 for (VpnInstanceInfo vpnInfo: vpnInfos) {
499 ConcurrentMap<FibInfo, Object> fibInfos = l3Manager.getVpnInstanceManager().
500 getLocalFibInfosForRdCache(vpnInfo.getRouteDistinguisher());
501 s_logger.info("Number of fib infos to configure is "+fibInfos.size());
502 for (FibInfo fibInfo : fibInfos.keySet()) {
504 bgpThriftClient.addPrefix(vpnInfo.getRouteDistinguisher(), fibInfo.getDestinationPrefix(),
505 fibInfo.getNextHopPrefix(), (int) fibInfo.getLabel());
506 } catch (TException t) {
507 s_logger.error("Failed to push route to bgp due to Transport error" );
509 addPrefix(vpnInfo.getRouteDistinguisher(), fibInfo.getDestinationPrefix(),
510 fibInfo.getNextHopPrefix(), (int) fibInfo.getLabel());
511 } catch (Exception e) {
512 s_logger.error("Failed to push route to bgp ", e);
521 public void disconnect() {
522 bgpThriftClient.disconnect();
525 public void setRoute(Route r) {
526 s_logger.info("Setting route in VPN Manager");
527 //l3Manager.getVpnInstanceManager().addRoute(r.getRd(), r.getPrefix(), r.getNexthop(), r.getLabel());
530 /* For testing purposes */
531 /*public String ribGet() {
532 String family = "ipv4";
533 String format = "json";
536 List<Route> routeList = bgpThriftClient.getRoutes();
537 Iterator<Route> iter = routeList.iterator();
538 while(iter.hasNext()) {
539 Route r = iter.next();
540 System.out.println("Route:: vrf:" + r.getRd() + " Prefix: " + r.getPrefix() + " Nexthop: " + r.getNexthop() + "Label: " + r.getLabel());
542 } catch (Exception e) {
543 s_logger.error("Failed getting bgp routes ", e);