87b02946af274cbb246b0bc689de43240264369e
[netvirt.git] / fibmanager / shell / src / main / java / org / opendaylight / netvirt / fibmanager / shell / ShowFibCommand.java
1 /*
2  * Copyright (c) 2015 - 2017 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.fibmanager.shell;
10
11 import java.io.PrintStream;
12 import java.net.Inet4Address;
13 import java.net.Inet6Address;
14 import java.net.InetAddress;
15 import java.net.UnknownHostException;
16 import java.util.List;
17 import java.util.Locale;
18 import javax.annotation.Nullable;
19 import org.apache.karaf.shell.commands.Argument;
20 import org.apache.karaf.shell.commands.Command;
21 import org.apache.karaf.shell.commands.Option;
22 import org.apache.karaf.shell.console.OsgiCommandSupport;
23 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
26 import org.opendaylight.genius.datastoreutils.ExpectedDataObjectNotFoundException;
27 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
28 import org.opendaylight.netvirt.fibmanager.api.FibHelper;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.VrfEntryBase.EncapType;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentrybase.RoutePaths;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 @Command(scope = "vpnservice", name = "fib-show", description = "Displays fib entries.\t"
39         + "To get more help use cli fib-show fullHelp")
40 public class ShowFibCommand extends OsgiCommandSupport {
41
42     private static final Logger LOG = LoggerFactory.getLogger(ShowFibCommand.class);
43
44     private static final String TABULAR_FORMAT = "   %-7s  %-20s  %-20s  %-7s  %-7s";
45     private static final String HEADER = String.format(TABULAR_FORMAT, "RD", "Prefix", "NextHop", "Label", "Origin")
46                                            + "\n   -------------------------------------------------------------------";
47     private static final String ADDRFAMILY = "--addr-family";
48     private static final String SUBNET = "--subnet";
49
50     @Argument(name = "addFam|fullHelp", description = "type of address families to show, or full help cli",
51             required = false, multiValued = false)
52     private final String options = null;
53
54     @Option(name = ADDRFAMILY, aliases = {"-af"},
55             description = "show address family ipv4 and/or ipv6 and/or l2vpn",
56             required = false, multiValued = true)
57     private final List<String> addrFamList = null;
58
59     @Option(name = SUBNET, aliases = {"-sub"},
60             description = "show only one IP or subnet sorted by mask ex \"x.x.x.x/32\" or \"2001::1/128\"",
61             required = false, multiValued = true)
62     private final String prefixOrSubnetOption = null;
63     private String prefixOrSubnet = null;
64
65     private SingleTransactionDataBroker singleTxDb;
66
67     public void setDataBroker(DataBroker dataBroker) {
68         this.singleTxDb = new SingleTransactionDataBroker(dataBroker);
69     }
70
71     @Override
72     @Nullable
73     protected Object doExecute() {
74         PrintStream console = session.getConsole();
75         if (prefixOrSubnetOption != null && prefixOrSubnetOption.length() > 0) {
76             prefixOrSubnet = prefixOrSubnetOption.replace("[", "");
77             prefixOrSubnet = prefixOrSubnet.replace("]", "");
78             if (!prefixOrSubnet.contains("/")) {
79                 String maskFull = null;
80                 try {
81                     Inet4Address tempAdd = (Inet4Address) InetAddress.getByName(prefixOrSubnet);
82                     maskFull = "/32";
83                 } catch (SecurityException | UnknownHostException | ClassCastException e) {
84                     maskFull = null;
85                 }
86                 if (maskFull == null) {
87                     try {
88                         Inet6Address tempAdd = (Inet6Address) InetAddress.getByName(prefixOrSubnet);
89                         maskFull = "/128";
90                     } catch (SecurityException | UnknownHostException | ClassCastException e) {
91                         maskFull = null;
92                     }
93                 }
94                 if (maskFull == null) {
95                     console.println("a part of cli " + SUBNET + " is wrong => " + prefixOrSubnet);
96                     return usage(console);
97                 }
98                 prefixOrSubnet += maskFull;
99             }
100         }
101         console.println(HEADER);
102         if (options == null && prefixOrSubnet == null && (addrFamList == null || addrFamList.isEmpty())) {
103             InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
104             try {
105                 FibEntries fibEntries = singleTxDb.syncRead(LogicalDatastoreType.CONFIGURATION, id);
106
107                 List<VrfTables> vrfTablesList = fibEntries.getVrfTables();
108                 if (vrfTablesList == null || vrfTablesList.isEmpty()) {
109                     console.println(" No Fib entries found");
110                     return null;
111                 }
112
113                 for (VrfTables vrfTable : vrfTablesList) {
114                     printVrfTable(vrfTable, console);
115                 }
116             } catch (ExpectedDataObjectNotFoundException e404) {
117                 /* This is always thrown the first time FIB DS is accessed,
118                    and no route have yet been configured in it. So, no need to print FATAL on the console.
119                 */
120                 String errMsg = "FATAL: fib-entries container is missing from MD-SAL";
121                 LOG.error(errMsg, e404);
122             } catch (ReadFailedException rfe) {
123                 String errMsg = "Internal Error occurred while processing vpnservice:fib-show command";
124                 console.println("\n" + errMsg);
125                 LOG.error(errMsg, rfe);
126             }
127             return null;
128         } else {
129             String optionsLowerCase = options != null ? options.toLowerCase(Locale.getDefault()) : "";
130             switch (optionsLowerCase) {
131                 case "fullhelp":
132                     return usage(console);
133                 default :
134             }
135
136             if ((addrFamList == null || addrFamList.isEmpty()) && (prefixOrSubnet == null
137                     || prefixOrSubnet.indexOf("/") < 5)) {
138                 console.println("any address family is requiered or " + SUBNET + " is wrong");
139                 usage(console);
140             } else {
141                 boolean isIpv4 = false;
142                 boolean isIpv6 = false;
143                 boolean isL2vpn = false;
144                 if (addrFamList != null && addrFamList.size() > 0) {
145                     for (String addF : addrFamList) {
146                         switch (addF.toLowerCase(Locale.getDefault())) {
147                             case "ipv4":
148                                 isIpv4 = true;
149                                 break;
150                             case "ipv6":
151                                 isIpv6 = true;
152                                 break;
153                             case "l2vpn":
154                                 isL2vpn = true;
155                                 break;
156                             default :
157                         }
158                     }
159                 }
160                 InstanceIdentifier<FibEntries> id = InstanceIdentifier.create(FibEntries.class);
161                 try {
162                     FibEntries fibEntries = singleTxDb.syncRead(LogicalDatastoreType.CONFIGURATION, id);
163
164                     List<VrfTables> vrfTablesList = fibEntries.getVrfTables();
165                     if (vrfTablesList == null || vrfTablesList.isEmpty()) {
166                         console.println(" No Fib entries found");
167                         return null;
168                     }
169
170                     for (VrfTables vrfTable : vrfTablesList) {
171                         printVrfTable(vrfTable, console, isIpv4, isIpv6, isL2vpn, prefixOrSubnet);
172                     }
173                 } catch (ExpectedDataObjectNotFoundException e404) {
174                     String errMsg = "FATAL: fib-entries container is missing from MD-SAL";
175                     console.println("\n" + errMsg);
176                     LOG.error(errMsg, e404);
177                 } catch (ReadFailedException rfe) {
178                     String errMsg = "Internal Error occurred while processing vpnservice:fib-show command";
179                     console.println("\n" + errMsg);
180                     LOG.error(errMsg, rfe);
181                 }
182                 return null;
183             }
184         }
185         return null;
186     }
187
188     private void printVrfTable(VrfTables vrfTable, PrintStream console) {
189         printVrfTable(vrfTable, console, true, true, true, null);
190     }
191
192     private void printVrfTable(VrfTables vrfTable, PrintStream console, boolean isIpv4, boolean isIpv6,
193             boolean isL2vpn, @Nullable String inputPrefixOrSubnet) {
194
195         List<VrfEntry> vrfEntries = vrfTable.getVrfEntry();
196         if (vrfEntries == null) {
197             LOG.warn("Null vrfEntries found for VPN with rd={}", vrfTable.getRouteDistinguisher());
198             return;
199         }
200
201         for (VrfEntry vrfEntry : vrfEntries) {
202             boolean showIt = false;
203             if (isIpv4 && isIpv6 && isL2vpn) {
204                 showIt = true;
205             }
206             if (!showIt && isIpv4) {
207                 LOG.debug("is ipv4 address family=> vrfEntry.getDestPrefix() = {}", vrfEntry.getDestPrefix());
208                 showIt = FibHelper.isIpv4Prefix(vrfEntry.getDestPrefix());
209             }
210             if (!showIt && isIpv6) {
211                 LOG.debug("is ipv6 address family=> vrfEntry.getDestPrefix() = {}", vrfEntry.getDestPrefix());
212                 showIt = FibHelper.isIpv6Prefix(vrfEntry.getDestPrefix());
213             }
214             if (!showIt && isL2vpn) {
215                 if (vrfEntry.getEncapType() != null && !EncapType.Mplsgre.equals(vrfEntry.getEncapType())) {
216                     LOG.debug("is l2vpn address family=> vrfEntry.getEncapType() = {}", vrfEntry.getEncapType());
217                     showIt = true;
218                 }
219             }
220             if (!showIt && inputPrefixOrSubnet != null) {
221                 showIt = FibHelper.isBelongingPrefix(vrfEntry.getDestPrefix(), inputPrefixOrSubnet);
222             }
223             if (!showIt) {
224                 continue;
225             }
226             List<RoutePaths> routePaths = vrfEntry.getRoutePaths();
227             if (routePaths == null || routePaths.isEmpty()) {
228                 console.println(String.format(TABULAR_FORMAT,
229                                               vrfTable.getRouteDistinguisher(), vrfEntry.getDestPrefix(),
230                                               "local", routePaths == null ? "<not set>" : "<empty>",
231                                               vrfEntry.getOrigin()));
232                 continue;
233             }
234             for (RoutePaths routePath : routePaths) {
235                 console.println(String.format(TABULAR_FORMAT,
236                                               vrfTable.getRouteDistinguisher(), vrfEntry.getDestPrefix(),
237                                               routePath.getNexthopAddress(), routePath.getLabel(),
238                                               vrfEntry.getOrigin()));
239             }
240         }
241     }
242
243     @Nullable
244     private Object usage(PrintStream console) {
245         String nl = System.getProperty("line.separator");
246         console.println("===================================================");
247         console.println("usage cli =>" + nl);
248         console.println("fib-show --help => to get the current help");
249         console.println("fib-show fullHelp => to get the FULL help" + nl);
250         console.println("fib-show -af ipv4  => to get ipv4 address family");
251         console.println("fib-show -af ipv4 -af ipv6 => to get ipv4 and ipv6 address family");
252         console.println("fib-show -af ipv4 -af ipv6 -af l2vpn => to get ipv4 and ipv6 and l2vpn address family");
253         console.println("---------------------------------------------------");
254         console.println("fib-show -sub 40.1.1.0/24 => to get all IPv4 from fib belonging to this subnet");
255         console.println("fib-show -sub 40.1.1.1/32 => to get the IPv4 from fib");
256         console.println("---------------------------------------------------");
257         console.println("fib-show -sub 2001::1/64 => to get all IPv6 from fib belonging to this subnet");
258         console.println("fib-show -sub 2001::1/128 => to get all IPv6 from fib");
259         console.println("===================================================");
260         return null;
261     }
262
263
264 }