blob: 5a4ecdeaffaf141497a0126d0b35a2b6e1c81bca [file] [log] [blame]
Yi Tseng2e5d99e2017-06-06 10:58:46 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2017-present Open Networking Foundation
Yi Tseng2e5d99e2017-06-06 10:58:46 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.dhcprelay.cli;
18
19import org.apache.karaf.shell.commands.Command;
20import org.onlab.packet.Ip4Address;
21import org.onlab.packet.IpAddress;
22import org.onlab.packet.MacAddress;
23import org.onlab.packet.VlanId;
Yi Tseng13a41a12017-07-26 13:45:01 -070024import org.onlab.util.Tools;
Yi Tseng2e5d99e2017-06-06 10:58:46 -070025import org.onosproject.cli.AbstractShellCommand;
26import org.onosproject.core.ApplicationId;
27import org.onosproject.core.CoreService;
Yi Tsenge72fbb52017-08-02 15:03:31 -070028import org.onosproject.dhcprelay.config.DefaultDhcpRelayConfig;
Yi Tseng2e5d99e2017-06-06 10:58:46 -070029import org.onosproject.dhcprelay.DhcpRelayManager;
Yi Tseng51301292017-07-28 13:02:59 -070030import org.onosproject.dhcprelay.api.DhcpRelayService;
Yi Tsenge72fbb52017-08-02 15:03:31 -070031import org.onosproject.dhcprelay.config.DhcpServerConfig;
Yi Tseng2e5d99e2017-06-06 10:58:46 -070032import org.onosproject.dhcprelay.store.DhcpRecord;
33import org.onosproject.net.ConnectPoint;
34import org.onosproject.net.Host;
35import org.onosproject.net.HostId;
36import org.onosproject.net.config.NetworkConfigRegistry;
37import org.onosproject.net.host.HostService;
38
Yi Tseng2e5d99e2017-06-06 10:58:46 -070039import java.util.Collection;
Yi Tseng13a41a12017-07-26 13:45:01 -070040import java.util.function.Predicate;
Yi Tseng2e5d99e2017-06-06 10:58:46 -070041
42/**
43 * Prints DHCP server and DHCP relay status.
44 */
45@Command(scope = "onos", name = "dhcp-relay", description = "DHCP relay app cli.")
46public class DhcpRelayCommand extends AbstractShellCommand {
47 private static final String HEADER = "DHCP relay records ([D]: Directly connected):";
48 private static final String NO_RECORDS = "No DHCP relay record found";
Yi Tseng13a41a12017-07-26 13:45:01 -070049 private static final String HOST = "id=%s/%s, locations=%s%s, last-seen=%s, IPv4=%s, IPv6=%s";
50 private static final String DHCP_SERVER_GW = "DHCP Server: %s, %s via %s (Mac: %s)";
51 private static final String DHCP_SERVER = "DHCP Server: %s, %s (Mac: %s)";
Yi Tseng2e5d99e2017-06-06 10:58:46 -070052 private static final String MISSING_SERVER_CFG = "DHCP Server info not available";
Yi Tseng13a41a12017-07-26 13:45:01 -070053 private static final String DIRECTLY = "[D]";
54 private static final String EMPTY = "";
55 private static final String NA = "N/A";
56 private static final String STATUS_FMT = "[%s, %s]";
57 private static final String STATUS_FMT_NH = "[%s via %s, %s]";
Yi Tseng2e5d99e2017-06-06 10:58:46 -070058
59 private static final DhcpRelayService DHCP_RELAY_SERVICE = get(DhcpRelayService.class);
60 private static final NetworkConfigRegistry CFG_SERVICE = get(NetworkConfigRegistry.class);
61 private static final HostService HOST_SERVICE = get(HostService.class);
62 private static final CoreService CORE_SERVICE = get(CoreService.class);
63 private static final ApplicationId APP_ID =
64 CORE_SERVICE.getAppId(DhcpRelayManager.DHCP_RELAY_APP);
65
Yi Tseng13a41a12017-07-26 13:45:01 -070066
Yi Tseng2e5d99e2017-06-06 10:58:46 -070067 @Override
68 protected void execute() {
Yi Tsenge72fbb52017-08-02 15:03:31 -070069 DefaultDhcpRelayConfig cfg = CFG_SERVICE.getConfig(APP_ID, DefaultDhcpRelayConfig.class);
70 if (cfg == null || cfg.dhcpServerConfigs().size() == 0) {
Yi Tseng2e5d99e2017-06-06 10:58:46 -070071 print(MISSING_SERVER_CFG);
72 return;
73 }
74
75 // DHCP server information
Yi Tsenge72fbb52017-08-02 15:03:31 -070076 // TODO: currently we pick up first DHCP server config.
77 // Will use other server configs in the future.
78 DhcpServerConfig serverConfig = cfg.dhcpServerConfigs().get(0);
79
80 ConnectPoint connectPoint = serverConfig.getDhcpServerConnectPoint().orElse(null);
81 Ip4Address gatewayAddress = serverConfig.getDhcpGatewayIp4().orElse(null);
82 Ip4Address serverIp = serverConfig.getDhcpServerIp4().orElse(null);
Yi Tseng13a41a12017-07-26 13:45:01 -070083 String serverMac = DHCP_RELAY_SERVICE.getDhcpServerMacAddress()
84 .map(MacAddress::toString).orElse(NA);
Yi Tseng2e5d99e2017-06-06 10:58:46 -070085 if (gatewayAddress != null) {
Yi Tseng13a41a12017-07-26 13:45:01 -070086 print(DHCP_SERVER_GW, connectPoint, serverIp, gatewayAddress, serverMac);
Yi Tseng2e5d99e2017-06-06 10:58:46 -070087 } else {
Yi Tseng13a41a12017-07-26 13:45:01 -070088 print(DHCP_SERVER, connectPoint, serverIp, serverMac);
Yi Tseng2e5d99e2017-06-06 10:58:46 -070089 }
90
91 // DHCP records
92 Collection<DhcpRecord> records = DHCP_RELAY_SERVICE.getDhcpRecords();
93 if (records.isEmpty()) {
94 print(NO_RECORDS);
95 return;
96 }
97 print(HEADER);
Yi Tseng13a41a12017-07-26 13:45:01 -070098 records.forEach(record -> print(HOST,
99 record.macAddress(),
100 record.vlanId(),
101 record.locations(),
102 record.directlyConnected() ? DIRECTLY : EMPTY,
103 Tools.timeAgo(record.lastSeen()),
104 ip4State(record),
105 ip6State(record)));
Yi Tseng2e5d99e2017-06-06 10:58:46 -0700106 }
107
Yi Tseng13a41a12017-07-26 13:45:01 -0700108 private String ip4State(DhcpRecord record) {
109 String nextHopIp = findNextHopIp(IpAddress::isIp4,
110 record.nextHop().orElse(null),
111 record.vlanId());
112 return ipState(record.ip4Address().map(Object::toString).orElse(NA),
113 record.ip4Status().map(Object::toString).orElse(NA),
114 record.directlyConnected(),
115 nextHopIp);
116 }
117
118 private String ip6State(DhcpRecord record) {
119 String nextHopIp = findNextHopIp(IpAddress::isIp6,
120 record.nextHop().orElse(null),
121 record.vlanId());
122 return ipState(record.ip6Address().map(Object::toString).orElse(NA),
123 record.ip6Status().map(Object::toString).orElse(NA),
124 record.directlyConnected(),
125 nextHopIp);
126 }
127
128 private String ipState(String ipAddress, String status,
129 boolean directlyConnected,
130 String nextHopIp) {
131 if (directlyConnected) {
132 return String.format(STATUS_FMT, ipAddress, status);
133 } else {
134 return String.format(STATUS_FMT_NH, ipAddress, nextHopIp, status);
135 }
136 }
137
138 private String findNextHopIp(Predicate<IpAddress> ipFilter, MacAddress nextHopMac, VlanId vlanId) {
139 if (ipFilter == null || nextHopMac == null || vlanId == null) {
140 return NA;
141 }
142 Host host = HOST_SERVICE.getHost(HostId.hostId(nextHopMac, vlanId));
143 if (host == null) {
144 return NA;
145 }
146 return host.ipAddresses().stream()
147 .filter(ipFilter)
148 .filter(ip -> !ip.isLinkLocal())
149 .map(Object::toString)
150 .findFirst()
151 .orElse(NA);
Yi Tseng2e5d99e2017-06-06 10:58:46 -0700152 }
153}