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
9 package org.opendaylight.netvirt.bgpmanager.oam;
11 import java.io.BufferedReader;
12 import java.io.BufferedWriter;
14 import java.io.FileNotFoundException;
15 import java.io.FileWriter;
16 import java.io.IOException;
17 import java.io.InputStreamReader;
18 import java.io.PrintWriter;
19 import java.lang.management.ManagementFactory;
20 import java.net.Socket;
21 import java.net.SocketTimeoutException;
22 import java.net.UnknownHostException;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
27 import java.util.Scanner;
28 import java.util.TimerTask;
29 import java.util.regex.Matcher;
30 import java.util.regex.Pattern;
31 import javax.management.JMException;
32 import javax.management.MBeanServer;
33 import javax.management.ObjectName;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
38 public class BgpCounters extends TimerTask {
40 private static final Logger LOGGER = LoggerFactory.getLogger(BgpCounters.class);
41 private static BgpCountersBroadcaster bgpStatsBroadcaster = null;
42 private MBeanServer bgpStatsServer = null;
43 private Map<String, String> countersMap = new HashMap<>();
44 private String bgpSdncMip = "127.0.0.1";
46 public BgpCounters(String mipAddress) {
47 bgpSdncMip = mipAddress;
53 LOGGER.debug("Fetching counters from BGP");
55 fetchCmdOutputs("cmd_ip_bgp_summary.txt", "show ip bgp summary");
56 fetchCmdOutputs("cmd_bgp_ipv4_unicast_statistics.txt", "show bgp ipv4 unicast statistics");
57 fetchCmdOutputs("cmd_ip_bgp_vpnv4_all.txt", "show ip bgp vpnv4 all");
60 if (LOGGER.isDebugEnabled()) {
63 if (bgpStatsBroadcaster == null) {
64 //First time execution
66 bgpStatsBroadcaster = new BgpCountersBroadcaster();
67 bgpStatsServer = ManagementFactory.getPlatformMBeanServer();
68 ObjectName bgpStatsObj = new ObjectName("SDNC.PM:type=BgpCountersBroadcaster");
69 bgpStatsServer.registerMBean(bgpStatsBroadcaster, bgpStatsObj);
70 LOGGER.info("BGP Counters MBean Registered :::");
71 } catch (JMException e) {
72 LOGGER.error("Adding a NotificationBroadcaster failed.", e);
76 bgpStatsBroadcaster.setBgpCountersMap(countersMap);
77 LOGGER.debug("Finished updating the counters from BGP");
78 } catch (IOException e) {
79 LOGGER.error("Failed to publish bgp counters ", e);
83 private void dumpCounters() {
84 for (Map.Entry<String, String> entry : countersMap.entrySet()) {
85 LOGGER.debug("{}, Value = {}", entry.getKey(), entry.getValue());
89 void fetchCmdOutputs(String filename, String cmdName) throws IOException {
90 try (Socket socket = new Socket(bgpSdncMip, 2605);
91 PrintWriter toRouter = new PrintWriter(socket.getOutputStream(), true);
92 BufferedReader fromRouter = new BufferedReader(new InputStreamReader(socket.getInputStream()));
93 BufferedWriter toFile = new BufferedWriter(new FileWriter(filename, true))) {
94 socket.setSoTimeout(2 * 1000);
96 // Wait for the password prompt
97 StringBuilder sb = new StringBuilder();
99 char[] cbuf = new char[10];
100 while (!sb.toString().contains("Password:")) {
101 if ((read = fromRouter.read(cbuf)) == -1) {
102 LOGGER.error("Connection closed by BGPd.");
105 sb.append(cbuf, 0, read);
109 toRouter.println(BgpConstants.QBGP_VTY_PASSWORD);
111 // Wait for the prompt (ending with '>' or '#')
112 sb = new StringBuilder();
113 String prompt = null;
114 while (prompt == null) {
115 switch (read = fromRouter.read()) {
117 LOGGER.error("Connection closed by BGPd, read {}", sb.toString());
122 prompt = sb.toString().trim();
125 sb.append((char) read);
131 toRouter.println("en");
134 while ((read = fromRouter.read()) != '#') {
136 LOGGER.error("Connection closed by BGPd, read {}", sb.toString());
142 toRouter.println(cmdName);
144 // Read all the router's output
145 sb = new StringBuilder();
146 cbuf = new char[1024];
147 while ((read = fromRouter.read(cbuf)) != -1) {
148 sb.append(cbuf, 0, read);
151 // Only keep output up to the last prompt
152 int lastPromptIndex = sb.lastIndexOf(prompt);
153 if (lastPromptIndex >= 0) {
154 sb.delete(lastPromptIndex, sb.length());
158 toFile.write(sb.toString().trim());
159 } catch (UnknownHostException e) {
160 LOGGER.error("Unknown host {}", bgpSdncMip, e);
161 } catch (SocketTimeoutException e) {
162 LOGGER.error("Socket timeout", e);
163 } catch (IOException e) {
164 LOGGER.error("I/O error", e);
168 private static boolean validate(final String ip) {
169 if (ip == null || ip.equals("")) {
172 Pattern pattern = Pattern.compile("^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
173 Matcher matcher = pattern.matcher(ip);
174 return matcher.matches();
179 * The below function parses the output of "show ip bgp summary" saved in a file.
180 * Below is the snippet for the same :-
182 BGP router identifier 10.183.254.53, local AS number 101
184 Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
185 10.183.254.76 4 100 3 4 0 0 0 00:01:27 0
187 Total number of neighbors 1
191 private void parseIpBgpSummary() {
192 File file = new File("cmd_ip_bgp_summary.txt");
194 try (Scanner scanner = new Scanner(file)) {
195 boolean startEntries = false;
196 while (scanner.hasNextLine()) {
197 String str = scanner.nextLine();
198 if (str.contains("State/PfxRcd")) {
200 } else if (startEntries) {
201 String[] result = str.split("\\s+");
202 if (result.length < 5) {
205 String strIp = result[0].trim();
206 if (!validate(strIp)) {
209 final String as = result[2];
210 final String rx = result[3];
211 final String tx = result[4];
214 BgpConstants.BGP_COUNTER_NBR_PKTS_RX + ":BGP_Nbr_IP_" + strIp + "_AS_" + as
218 BgpConstants.BGP_COUNTER_NBR_PKTS_TX + ":BGP_Nbr_IP_" + strIp + "_AS_" + as + "_PktsSent",
222 } catch (IOException e) {
223 LOGGER.error("Could not process the file {}", file.getAbsolutePath());
227 * The below function parses the output of "show bgp ipv4 unicast statistics" saved in a file.
228 * Below is the sample output for the same :-
230 BGP IPv4 Unicast RIB statistics
237 private void parseBgpIpv4UnicastStatistics() {
238 File file = new File("cmd_bgp_ipv4_unicast_statistics.txt");
240 try (Scanner scanner = new Scanner(file)) {
241 while (scanner.hasNextLine()) {
242 String instr = scanner.nextLine();
243 if (instr.contains("Total Prefixes")) {
244 String[] result = instr.split(":");
245 if (result.length > 1) {
246 totPfx = result[1].trim();
253 } catch (IOException e) {
254 LOGGER.error("Could not process the file {}", file.getAbsolutePath());
257 countersMap.put(BgpConstants.BGP_COUNTER_TOTAL_PFX, totPfx);
261 * The below function parses the output of "show ip bgp vpnv4 all" saved in a file.
262 * Below is the sample output for the same :-
263 * show ip bgp vpnv4 all
265 BGP table version is 0, local router ID is 10.183.181.21
267 Route Distinguisher: 100:1
268 *>i15.15.15.15/32 10.183.181.25 0 100 0 ?
269 *>i17.18.17.17/32 10.183.181.25 0 100 0 ?
270 *>i17.18.17.17/32 10.183.181.25 0 100 0 ?
271 *>i17.18.17.17/32 10.183.181.25 0 100 0 ?
272 Route Distinguisher: 100:2
273 *>i16.16.16.16/32 10.183.181.25 0 100 0 ?
274 *>i18.18.18.18/32 10.183.181.25 0 100 0 ?
275 *>i17.18.17.17/32 10.183.181.25 0 100 0 ?
278 private void parseIpBgpVpnv4All() {
279 File file = new File("cmd_ip_bgp_vpnv4_all.txt");
280 List<String> inputStrs = new ArrayList<>();
282 try (Scanner scanner = new Scanner(file)) {
283 while (scanner.hasNextLine()) {
284 inputStrs.add(scanner.nextLine());
286 } catch (IOException e) {
287 LOGGER.error("Could not process the file {}", file.getAbsolutePath());
290 for (int i = 0; i < inputStrs.size(); i++) {
291 String instr = inputStrs.get(i);
292 if (instr.contains("Route Distinguisher")) {
293 String[] result = instr.split(":");
294 String rd = result[1].trim() + "_" + result[2].trim();
295 i = processRouteCount(rd, i + 1, inputStrs);
298 /*populate the "BgpTotalPrefixes" counter by combining
299 the prefixes that are calculated per RD basis*/
300 int bgpTotalPfxs = calculateBgpTotalPrefixes();
301 LOGGER.trace("BGP Total Prefixes:{}",bgpTotalPfxs);
302 countersMap.put(BgpConstants.BGP_COUNTER_TOTAL_PFX,String.valueOf(bgpTotalPfxs));
305 private int processRouteCount(String rd, int startIndex, List<String> inputStrs) {
306 int num = startIndex;
308 String key = BgpConstants.BGP_COUNTER_RD_ROUTE_COUNT + ":BGP_RD_" + rd + "_route_count";
310 for (String str = inputStrs.get(num); str != null && !str.trim().equals("") && num < inputStrs.size();
311 str = inputStrs.get(num)) {
312 if (str.contains("Route Distinguisher")) {
313 countersMap.put(key, Integer.toString(routeCount));
318 if (num == inputStrs.size()) {
322 if (routeCount == 0) {
323 // Erroneous condition, should never happen.
324 // Implies that the file contains marker for RD without routes.
325 // will form an infinite loop if not broken
326 // by sending a big number back.
327 return Integer.MAX_VALUE;
329 countersMap.put(key, Integer.toString(routeCount));
333 private int calculateBgpTotalPrefixes() {
334 return countersMap.entrySet().stream().filter(entry -> entry.getKey().contains(BgpConstants
335 .BGP_COUNTER_RD_ROUTE_COUNT)).map(Map.Entry::getValue).mapToInt(Integer::parseInt).sum();
338 private void resetCounters() {
340 resetFile("cmd_ip_bgp_summary.txt");
341 resetFile("cmd_bgp_ipv4_unicast_statistics.txt");
342 resetFile("cmd_ip_bgp_vpnv4_all.txt");
345 static void resetFile(String fileName) {
346 File file = (new File(fileName));
347 if (!file.delete()) {
348 try (PrintWriter pw = new PrintWriter(file)) {
350 } catch (FileNotFoundException e) {
356 static Map<String, String> parseIpBgpVpnv4AllSummary(Map<String, String> countMap) {
357 File file = new File("cmd_ip_bgp_vpnv4_all_summary.txt");
359 try (Scanner scanner = new Scanner(file)) {
360 boolean startEntries = false;
361 while (scanner.hasNextLine()) {
362 String str = scanner.nextLine();
363 LOGGER.trace("str is:: {}", str);
364 if (str.contains("State/PfxRcd")) {
366 } else if (startEntries) {
367 String[] result = str.split("\\s+");
368 if (result.length > 9) {
369 String strIp = result[0].trim();
370 LOGGER.trace("strIp " + strIp);
372 if (!validate(strIp)) {
375 String statePfxRcvd = result[9];
376 countMap.put(strIp, statePfxRcvd);
380 } catch (IOException e) {
381 LOGGER.trace("Could not process the file {}", file.getAbsolutePath());