Merge "Bug 6515: Fix NPE for an IPv6 subnet without gateway"
[netvirt.git] / vpnservice / bgpmanager / bgpmanager-impl / src / main / java / org / opendaylight / netvirt / bgpmanager / oam / BgpCounters.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
9 package org.opendaylight.netvirt.bgpmanager.oam;
10
11 import javax.management.JMException;
12 import javax.management.MBeanServer;
13 import javax.management.ObjectName;
14 import java.io.*;
15 import java.lang.management.ManagementFactory;
16 import java.net.*;
17 import java.util.*;
18 import java.util.regex.Matcher;
19 import java.util.regex.Pattern;
20 import org.opendaylight.netvirt.bgpmanager.BgpManager;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24
25 /**
26  * Created by ECHIAPT on 8/4/2015.
27  */
28 public class BgpCounters extends TimerTask {
29
30     private static final Logger LOGGER = LoggerFactory.getLogger(BgpCounters.class);
31     public static BgpCountersBroadcaster bgpStatsBroadcaster = null;
32     public MBeanServer bgpStatsServer = null;
33     public  Map <String, String> countersMap = new HashMap<String, String>();
34     private String bgpSdncMip = "127.0.0.1";
35
36     public BgpCounters(String mipAddress) {
37         bgpSdncMip = mipAddress;
38     }
39
40     @Override
41     public void run () {
42         try {
43             if (LOGGER.isDebugEnabled()) {
44                 LOGGER.debug("Fetching counters from BGP at " + new Date());
45             }
46             resetCounters();
47             fetchCmdOutputs("cmd_ip_bgp_summary.txt","show ip bgp summary");
48             fetchCmdOutputs("cmd_bgp_ipv4_unicast_statistics.txt", "show bgp ipv4 unicast statistics");
49             fetchCmdOutputs("cmd_ip_bgp_vpnv4_all.txt", "show ip bgp vpnv4 all");
50             parse_ip_bgp_summary();
51             parse_bgp_ipv4_unicast_statistics();
52             parse_ip_bgp_vpnv4_all();
53             if (LOGGER.isDebugEnabled()) {
54                 dumpCounters();
55             }
56             if (bgpStatsBroadcaster == null) {
57                 //First time execution
58                 try {
59                     bgpStatsBroadcaster = new BgpCountersBroadcaster();
60                     bgpStatsServer = ManagementFactory.getPlatformMBeanServer();
61                     ObjectName bgpStatsObj = new ObjectName("SDNC.PM:type=BgpCountersBroadcaster");
62                     bgpStatsServer.registerMBean(bgpStatsBroadcaster, bgpStatsObj);
63                     LOGGER.info("BGP Counters MBean Registered :::");
64                 } catch (JMException e) {
65                     LOGGER.error("Adding a NotificationBroadcaster failed." , e);
66                     return;
67                 }
68             }
69             bgpStatsBroadcaster.setBgpCountersMap(countersMap);
70             if (LOGGER.isDebugEnabled()) {
71                 LOGGER.debug("Finished updating the counters from BGP at " + new Date());
72             }
73         } catch (Exception e) {
74             LOGGER.error("Failed to publish bgp counters ", e);
75         }
76     }
77
78     public void dumpCounters () {
79         Iterator<Map.Entry<String, String>> entries = countersMap.entrySet().iterator();
80         while (entries.hasNext()) {
81             Map.Entry<String, String> entry = entries.next();
82             LOGGER.debug(entry.getKey() + ", Value = " + entry.getValue());
83         }
84     }
85
86     public void fetchCmdOutputs (String filename, String cmdName) throws  IOException  {
87         Socket socket;
88         int serverPort = 2605;
89         String serverName = bgpSdncMip;
90         int sockTimeout = 2;
91         PrintWriter out_to_socket;
92         BufferedReader in_from_socket;
93         char cbuf[] = new char[10];
94         char op_buf[];
95         StringBuilder sb = new StringBuilder();
96         int ip, ret;
97         StringBuilder temp;
98         char ch, gt = '>', hash = '#';
99         String vtyPassword = BgpConstants.QBGP_VTY_PASSWORD;
100         String passwordCheckStr = "Password:";
101         String enableString = "en";
102         String prompt, replacedStr;
103
104         try
105         {
106             socket = new Socket(serverName, serverPort);
107
108         }
109         catch (UnknownHostException ioe) {
110             LOGGER.error("No host exists: " + ioe.getMessage());
111             return;
112         }
113         catch (IOException ioe) {
114             LOGGER.error("I/O error occured " + ioe.getMessage());
115             return;
116         }
117         try {
118             socket.setSoTimeout(sockTimeout*1000);
119             out_to_socket = new PrintWriter(socket.getOutputStream(), true);
120             in_from_socket = new BufferedReader(new InputStreamReader(socket.getInputStream()));
121
122         } catch (IOException ioe) {
123             LOGGER.error("IOException thrown.");
124             socket.close();
125             return;
126         }
127         while (true) {
128             try {
129                 ret = in_from_socket.read(cbuf);
130             }
131             catch (SocketTimeoutException ste) {
132                 LOGGER.error("Read from Socket timed Out while asking for password.");
133                 socket.close();
134                 return;
135             }
136             catch (IOException ioe) {
137                 LOGGER.error("Caught IOException");
138                 socket.close();
139                 return;
140             }
141             if (ret == -1) {
142                 LOGGER.error("Connection closed by BGPd.");
143                 socket.close();
144                 return;
145             } else {
146                 sb.append(cbuf);
147                 if (sb.toString().contains(passwordCheckStr)) {
148                     break;
149                 }
150             }
151         }
152
153         sb.setLength(0);
154         out_to_socket.println(vtyPassword);
155
156         while (true) {
157             try {
158                 ip = in_from_socket.read();
159             }
160             catch (SocketTimeoutException ste) {
161                 LOGGER.error(sb.toString());
162                 LOGGER.error("Read from Socket timed Out while verifying the password.");
163                 socket.close();
164                 return;
165             }
166             if (ip == (int)gt || ip == (int)hash) {
167                 break;
168             } else if (ip == -1) {
169                 LOGGER.error(sb.toString());
170                 LOGGER.error("Connection closed by BGPd.");
171                 socket.close();
172                 return;
173             } else {
174                 ch = (char)ip;
175                 sb.append(ch);
176
177             }
178         }
179
180         prompt = sb.toString();
181         prompt = prompt.trim();
182         sb.setLength(0);
183         out_to_socket.println(enableString);
184
185         while (true) {
186             try {
187                 ip = in_from_socket.read();
188             }
189             catch (SocketTimeoutException ste) {
190                 LOGGER.error(sb.toString());
191                 LOGGER.error("Read from Socket timed Out while keying the en keyword.");
192                 socket.close();
193                 return;
194             }
195             if (ip == (int)hash) {
196                 break;
197             } else if (ip == -1) {
198                 LOGGER.error(sb.toString());
199                 LOGGER.error("Connection closed by BGPd.");
200                 socket.close();
201                 return;
202             } else {
203                 ch = (char)ip;
204                 sb.append(ch);
205
206             }
207         }
208         sb.setLength(0);
209         temp = new StringBuilder();
210         File file;
211         FileWriter fileWritter;
212         BufferedWriter bufferWritter;
213
214         try {
215             file = new File(filename);
216             if (!file.exists()) {
217                 file.createNewFile();
218             }
219             fileWritter = new FileWriter(file.getName(), true);
220             bufferWritter = new BufferedWriter(fileWritter);
221         } catch (IOException e) {
222             return;
223         }
224         out_to_socket.println(cmdName);
225         temp.setLength(0);
226         while (true) {
227             try {
228                 op_buf = new char[100];
229                 ret = in_from_socket.read(op_buf);
230
231             } catch (SocketTimeoutException ste) {
232                 break;
233             } catch (SocketException soc) {
234                 break;
235             } catch (IOException ioe) {
236                 ioe.printStackTrace();
237                 break;
238             }
239
240             if (ret == -1) {
241                 break;
242             }
243             temp.append(op_buf);
244         }
245         String outputStr = temp.toString();
246         StringBuffer output = new StringBuffer();
247
248         outputStr.replaceAll("^\\s+|\\s+$", "");
249         output.append(outputStr);
250         if (output.toString().trim().contains(prompt)) {
251             int index = output.toString().lastIndexOf(prompt);
252             String newString = output.toString().substring(0, index);
253             output.setLength(0);
254             output.append(newString);
255         }
256         try {
257             bufferWritter.write(output.toString().trim());
258             temp.setLength(0);
259         } catch (IOException e) {
260             e.printStackTrace();
261             return;
262         }
263         try {
264             bufferWritter.close();
265             fileWritter.close();
266             socket.close();
267
268         } catch (IOException e) {
269             e.printStackTrace();
270             return;
271         }
272     }
273
274     public static boolean validate(final String ip){
275         if (ip == null || ip.equals("")) {
276             return false;
277         }
278         final String PATTERN =
279                 "^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
280         Pattern pattern = Pattern.compile(PATTERN);
281         Matcher matcher = pattern.matcher(ip);
282         return matcher.matches();
283     }
284
285
286     /*
287      * The below function parses the output of "show ip bgp summary" saved in a file.
288      * Below is the snippet for the same :-
289         <output>
290         BGP router identifier 10.183.254.53, local AS number 101
291         .....
292         Neighbor        V    AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
293         10.183.254.76   4   100       3       4        0    0    0 00:01:27        0
294         .........
295         Total number of neighbors 1
296         </output>
297      */
298
299     public void parse_ip_bgp_summary() {
300         File file = new File("cmd_ip_bgp_summary.txt");
301         Scanner scanner;
302         String lineFromFile;
303         List<String> inputStrs = new ArrayList<String>();
304         int i = 0;
305         String as,rx, tx;
306         boolean startEntries = false;
307         String[] result;
308         String StrIP;
309
310         try {
311             scanner = new Scanner(file);
312         } catch (IOException e) {
313             LOGGER.error("Could not process the file " + file.getAbsolutePath());
314             return ;
315         }
316         while (scanner.hasNextLine()) {
317
318             lineFromFile = scanner.nextLine();
319             inputStrs.add(lineFromFile);
320         }
321         String str;
322         StringBuilder NbrInfoKey = new StringBuilder();
323
324         while (i < inputStrs.size()) {
325             str = inputStrs.get(i);
326             if (str.contains("State/PfxRcd")) {
327                 startEntries = true;
328             } else if (startEntries == true) {
329                 result = str.split("\\s+");
330                try {
331                     StrIP = result[0].trim();
332                     if (!validate(StrIP)) {
333                         return;
334                     }
335                     as = result[2];
336                     rx = result[3];
337                     tx = result[4];
338
339                     NbrInfoKey.setLength(0);
340                     NbrInfoKey.append(BgpConstants.BGP_COUNTER_NBR_PKTS_RX).append(":").
341                            append("BGP_Nbr_IP_").append(StrIP).append("_AS_").append(as).append("_PktsReceived");
342                     countersMap.put(NbrInfoKey.toString(), rx);
343
344
345                     NbrInfoKey.setLength(0);
346                     NbrInfoKey.append(BgpConstants.BGP_COUNTER_NBR_PKTS_TX).append(":").
347                            append("BGP_Nbr_IP_").append(StrIP).append("_AS_").append(as).append("_PktsSent");
348                     countersMap.put(NbrInfoKey.toString(), tx);
349                 } catch (Exception e) {
350                     return;
351                 }
352             }
353             i++;
354         }
355  }
356     /*
357      * The below function parses the output of "show bgp ipv4 unicast statistics" saved in a file.
358      * Below is the sample output for the same :-
359         <output>
360         BGP IPv4 Unicast RIB statistics
361         ...
362         Total Prefixes                :            8
363         ......
364         </output>
365      */
366
367     public void parse_bgp_ipv4_unicast_statistics() {
368        File file = new File("cmd_bgp_ipv4_unicast_statistics.txt");
369        Scanner scanner;
370        String lineFromFile;
371        StringBuilder key = new StringBuilder();
372        String totPfx = "";
373        List<String> inputStrs = new ArrayList<String>();
374        try {
375            scanner = new Scanner(file);
376        } catch (IOException e) {
377            System.err.println("Could not process the file " + file.getAbsolutePath());
378            return ;
379        }
380        while (scanner.hasNextLine()) {
381
382            lineFromFile = scanner.nextLine();
383            inputStrs.add(lineFromFile);
384        }
385
386        int i = 0;
387        String instr;
388        while (i < inputStrs.size()) {
389            instr = inputStrs.get(i);
390            if (instr.contains("Total Prefixes")) {
391                String[] result = instr.split(":");
392                try {
393                    totPfx = result[1].trim();
394                } catch (Exception e) {
395                    totPfx = "0";
396                }
397                break;
398            }
399            i++;
400        }
401         key.setLength(0);
402         key.append(BgpConstants.BGP_COUNTER_TOTAL_PFX).append(":").
403                 append("Bgp_Total_Prefixes");
404         countersMap.put(key.toString(), totPfx);
405     }
406
407     /*
408      *  The below function parses the output of "show ip bgp vpnv4 all" saved in a file.
409      *  Below is the sample output for the same :-
410      *  show ip bgp vpnv4 all
411         <output>
412         BGP table version is 0, local router ID is 10.183.181.21
413         ......
414         Route Distinguisher: 100:1
415         *>i15.15.15.15/32   10.183.181.25            0    100      0 ?
416         *>i17.18.17.17/32   10.183.181.25            0    100      0 ?
417         *>i17.18.17.17/32   10.183.181.25            0    100      0 ?
418         *>i17.18.17.17/32   10.183.181.25            0    100      0 ?
419         Route Distinguisher: 100:2
420         *>i16.16.16.16/32   10.183.181.25            0    100      0 ?
421         *>i18.18.18.18/32   10.183.181.25            0    100      0 ?
422         *>i17.18.17.17/32   10.183.181.25            0    100      0 ?
423         </output>
424      */
425     public void parse_ip_bgp_vpnv4_all() {
426         File file = new File("cmd_ip_bgp_vpnv4_all.txt");
427         Scanner scanner;
428         String lineFromFile;
429         List<String> inputStrs = new ArrayList<String>();
430
431         try {
432             scanner = new Scanner(file);
433         } catch (IOException e) {
434             System.err.println("Could not process the file " + file.getAbsolutePath());
435             return ;
436         }
437         while (scanner.hasNextLine()) {
438             lineFromFile = scanner.nextLine();
439             inputStrs.add(lineFromFile);
440         }
441         int i = 0;
442         String instr, rd;
443         while (i < inputStrs.size()) {
444             instr = inputStrs.get(i);
445             if (instr.contains("Route Distinguisher")) {
446                 String[] result = instr.split(":");
447                 rd = result[1].trim() + "_" + result[2].trim();
448                 i = processRouteCount(rd, i + 1,  inputStrs);
449
450             }
451             i++;
452         }
453
454     }
455
456     public int processRouteCount(String rd, int startIndex, List<String> inputStrs) {
457         int num = startIndex, route_count = 0;
458         String str;
459         StringBuilder key = new StringBuilder();
460         str = inputStrs.get(num);
461
462         while (str != null && !str.trim().equals("") &&
463                 num <inputStrs.size()) {
464             if (str.contains("Route Distinguisher")) {
465                 key.setLength(0);
466                 key.append(BgpConstants.BGP_COUNTER_RD_ROUTE_COUNT).append(":").
467                         append("BGP_RD_").append(rd).append("_route_count");
468                 countersMap.put(key.toString(), Integer.toString(route_count));
469                 return num - 1;
470             }
471             route_count++;
472             num++;
473             if (num == inputStrs.size()) {
474                 break;
475             }
476             str = inputStrs.get(num);
477         }
478         if (route_count == 0) {
479             // Erroneous condition, should never happen.
480             // Implies that the file contains marker for RD  without routes.
481             // will form an infinite loop if not broken
482             // by sending a big number back.
483             return ~0;
484         }
485         key.setLength(0);
486         key.append(BgpConstants.BGP_COUNTER_RD_ROUTE_COUNT).append(":").
487                 append("BGP_RD_").append(rd).append("_route_count");
488         countersMap.put(key.toString(), Integer.toString(route_count));
489         return num - 1;
490     }
491
492     public void resetCounters() {
493         countersMap.clear();
494         resetFile("cmd_ip_bgp_summary.txt");
495         resetFile("cmd_bgp_ipv4_unicast_statistics.txt");
496         resetFile("cmd_ip_bgp_vpnv4_all.txt");
497     }
498
499     public static void resetFile(String fileName) {
500         File fileHndl = (new File(fileName));
501         PrintWriter writer;
502         boolean success;
503
504         success = fileHndl.delete();
505         if (!success) {
506             try {
507                 writer = new PrintWriter(fileHndl);
508                 writer.print("");
509                 writer.close();
510             } catch (Exception e) {
511                 return;
512             }
513         }
514
515     }
516
517     public static Map<String, String> parse_ip_bgp_vpnv4_all_summary(Map<String, String> countMap) {
518         File file = new File("cmd_ip_bgp_vpnv4_all_summary.txt");
519         Scanner scanner;
520         String lineFromFile;
521         List<String> inputStrs = new ArrayList<String>();
522         int i = 0;
523         boolean startEntries = false;
524         String[] result;
525         String StrIP;
526
527         try {
528             scanner = new Scanner(file);
529         } catch (IOException e) {
530             LOGGER.trace("Could not process the file " + file.getAbsolutePath());
531             return null;
532         }
533         while (scanner.hasNextLine()) {
534
535             lineFromFile = scanner.nextLine();
536             inputStrs.add(lineFromFile);
537         }
538         String str;
539         while (i < inputStrs.size()) {
540             str = inputStrs.get(i);
541             LOGGER.trace("str is:: {}", str);
542             if (str.contains("State/PfxRcd")) {
543                 startEntries = true;
544             } else if (startEntries == true) {
545                 result = str.split("\\s+");
546                 try {
547                     StrIP = result[0].trim();
548                     LOGGER.trace("strIP " + StrIP);
549
550                     if (!validate(StrIP)) {
551                         break;
552                     }
553                     String state_pfxRcvd = result[9];
554                     countMap.put(StrIP, state_pfxRcvd);
555                 } catch (Exception e) {
556                     LOGGER.trace("Exception {} caught while processing ip bgp vpnv4 all summary command output, e");
557                     i++;
558                     continue;
559                 }
560             }
561             i++;
562         }
563         return countMap;
564     }
565
566 }