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