bgpd: Show FQDN in show [ip] bgp output

We already show this information in `show [ip] bgp <prefix`, thus why don't
show it in global output. It's very handy when using at scale and to see
the whole picture instead of resolving neighbor manually.

It will show FQDN only if `bgp default show-hostname` is toggled.

Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
This commit is contained in:
Donatas Abraitis 2019-05-20 16:43:01 +03:00
parent 84cdd5b375
commit 25b5da8d50
7 changed files with 261 additions and 52 deletions

View File

@ -6930,6 +6930,13 @@ static void route_vty_short_status_out(struct vty *vty,
vty_out(vty, " ");
}
static char *bgp_nexthop_fqdn(struct peer *peer)
{
if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
return peer->hostname;
return NULL;
}
/* called from terminal list command */
void route_vty_out(struct vty *vty, struct prefix *p,
struct bgp_path_info *path, int display, safi_t safi,
@ -6946,6 +6953,7 @@ void route_vty_out(struct vty *vty, struct prefix *p,
bool nexthop_othervrf = false;
vrf_id_t nexthop_vrfid = VRF_DEFAULT;
const char *nexthop_vrfname = VRF_DEFAULT_NAME;
char *nexthop_fqdn = bgp_nexthop_fqdn(path->peer);
if (json_paths)
json_path = json_object_new_object();
@ -7041,42 +7049,58 @@ void route_vty_out(struct vty *vty, struct prefix *p,
if (json_paths) {
json_nexthop_global = json_object_new_object();
json_object_string_add(json_nexthop_global, "afi",
(af == AF_INET) ? "ip" : "ipv6");
json_object_string_add(json_nexthop_global,
(af == AF_INET) ? "ip" : "ipv6",
nexthop);
json_object_string_add(
json_nexthop_global, "afi",
nexthop_fqdn ? "fqdn"
: (af == AF_INET) ? "ip" : "ipv6");
json_object_string_add(
json_nexthop_global,
nexthop_fqdn ? "fqdn"
: (af == AF_INET) ? "ip" : "ipv6",
nexthop_fqdn ? nexthop_fqdn : nexthop);
json_object_boolean_true_add(json_nexthop_global,
"used");
} else
vty_out(vty, "%s%s", nexthop, vrf_id_str);
vty_out(vty, "%s%s",
nexthop_fqdn ? nexthop_fqdn : nexthop,
vrf_id_str);
} else if (safi == SAFI_EVPN) {
if (json_paths) {
json_nexthop_global = json_object_new_object();
json_object_string_add(json_nexthop_global, "ip",
inet_ntoa(attr->nexthop));
json_object_string_add(
json_nexthop_global,
nexthop_fqdn ? "fqdn" : "ip",
nexthop_fqdn ? nexthop_fqdn
: inet_ntoa(attr->nexthop));
json_object_string_add(json_nexthop_global, "afi",
"ipv4");
json_object_boolean_true_add(json_nexthop_global,
"used");
} else
vty_out(vty, "%-16s%s", inet_ntoa(attr->nexthop),
vty_out(vty, "%-16s%s",
nexthop_fqdn ?: inet_ntoa(attr->nexthop),
vrf_id_str);
} else if (safi == SAFI_FLOWSPEC) {
if (attr->nexthop.s_addr != 0) {
if (json_paths) {
json_nexthop_global = json_object_new_object();
json_object_string_add(
json_nexthop_global, "ip",
inet_ntoa(attr->nexthop));
json_nexthop_global,
nexthop_fqdn ? "fqdn" : "ip",
nexthop_fqdn
? nexthop_fqdn
: inet_ntoa(attr->nexthop));
json_object_string_add(json_nexthop_global,
"afi", "ipv4");
json_object_boolean_true_add(
json_nexthop_global,
"used");
} else {
vty_out(vty, "%-16s", inet_ntoa(attr->nexthop));
vty_out(vty, "%-16s",
nexthop_fqdn
? nexthop_fqdn
: inet_ntoa(attr->nexthop));
}
}
} else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
@ -7085,12 +7109,19 @@ void route_vty_out(struct vty *vty, struct prefix *p,
if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN))
json_object_string_add(
json_nexthop_global, "ip",
inet_ntoa(attr->mp_nexthop_global_in));
json_nexthop_global,
nexthop_fqdn ? "fqdn" : "ip",
nexthop_fqdn
? nexthop_fqdn
: inet_ntoa(
attr->mp_nexthop_global_in));
else
json_object_string_add(
json_nexthop_global, "ip",
inet_ntoa(attr->nexthop));
json_nexthop_global,
nexthop_fqdn ? "fqdn" : "ip",
nexthop_fqdn
? nexthop_fqdn
: inet_ntoa(attr->nexthop));
json_object_string_add(json_nexthop_global, "afi",
"ipv4");
@ -7100,7 +7131,9 @@ void route_vty_out(struct vty *vty, struct prefix *p,
char buf[BUFSIZ];
snprintf(buf, sizeof(buf), "%s%s",
inet_ntoa(attr->nexthop), vrf_id_str);
nexthop_fqdn ? nexthop_fqdn
: inet_ntoa(attr->nexthop),
vrf_id_str);
vty_out(vty, "%-16s", buf);
}
}
@ -7113,9 +7146,13 @@ void route_vty_out(struct vty *vty, struct prefix *p,
if (json_paths) {
json_nexthop_global = json_object_new_object();
json_object_string_add(
json_nexthop_global, "ip",
inet_ntop(AF_INET6, &attr->mp_nexthop_global,
buf, BUFSIZ));
json_nexthop_global,
nexthop_fqdn ? "fqdn" : "ip",
nexthop_fqdn
? nexthop_fqdn
: inet_ntop(AF_INET6,
&attr->mp_nexthop_global,
buf, BUFSIZ));
json_object_string_add(json_nexthop_global, "afi",
"ipv6");
json_object_string_add(json_nexthop_global, "scope",
@ -7127,10 +7164,14 @@ void route_vty_out(struct vty *vty, struct prefix *p,
|| (path->peer->conf_if)) {
json_nexthop_ll = json_object_new_object();
json_object_string_add(
json_nexthop_ll, "ip",
inet_ntop(AF_INET6,
&attr->mp_nexthop_local, buf,
BUFSIZ));
json_nexthop_ll,
nexthop_fqdn ? "fqdn" : "ip",
nexthop_fqdn
? nexthop_fqdn
: inet_ntop(
AF_INET6,
&attr->mp_nexthop_local,
buf, BUFSIZ));
json_object_string_add(json_nexthop_ll, "afi",
"ipv6");
json_object_string_add(json_nexthop_ll, "scope",
@ -7169,10 +7210,12 @@ void route_vty_out(struct vty *vty, struct prefix *p,
} else {
len = vty_out(
vty, "%s%s",
inet_ntop(
AF_INET6,
&attr->mp_nexthop_local,
buf, BUFSIZ),
nexthop_fqdn
? nexthop_fqdn
: inet_ntop(
AF_INET6,
&attr->mp_nexthop_local,
buf, BUFSIZ),
vrf_id_str);
len = 16 - len;
@ -7184,10 +7227,13 @@ void route_vty_out(struct vty *vty, struct prefix *p,
} else {
len = vty_out(
vty, "%s%s",
inet_ntop(AF_INET6,
&attr->mp_nexthop_global, buf,
BUFSIZ),
vrf_id_str);
nexthop_fqdn
? nexthop_fqdn
: inet_ntop(
AF_INET6,
&attr->mp_nexthop_global,
buf, BUFSIZ),
vrf_id_str);
len = 16 - len;
if (len < 1)
@ -8039,6 +8085,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
bool nexthop_self =
CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false;
int i;
char *nexthop_fqdn = bgp_nexthop_fqdn(path->peer);
if (json_paths) {
json_path = json_object_new_object();
@ -8174,21 +8221,33 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
|| safi == SAFI_EVPN) {
if (json_paths)
json_object_string_add(
json_nexthop_global, "ip",
inet_ntoa(
attr->mp_nexthop_global_in));
json_nexthop_global,
nexthop_fqdn ? "fqdn" : "ip",
nexthop_fqdn
? nexthop_fqdn
: inet_ntoa(
attr->mp_nexthop_global_in));
else
vty_out(vty, " %s",
inet_ntoa(
attr->mp_nexthop_global_in));
nexthop_fqdn
? nexthop_fqdn
: inet_ntoa(
attr->mp_nexthop_global_in));
} else {
if (json_paths)
json_object_string_add(
json_nexthop_global, "ip",
inet_ntoa(attr->nexthop));
json_nexthop_global,
nexthop_fqdn ? "fqdn" : "ip",
nexthop_fqdn
? nexthop_fqdn
: inet_ntoa(
attr->nexthop));
else
vty_out(vty, " %s",
inet_ntoa(attr->nexthop));
nexthop_fqdn
? nexthop_fqdn
: inet_ntoa(
attr->nexthop));
}
if (json_paths)
@ -8197,19 +8256,28 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
} else {
if (json_paths) {
json_object_string_add(
json_nexthop_global, "ip",
inet_ntop(AF_INET6,
&attr->mp_nexthop_global, buf,
INET6_ADDRSTRLEN));
json_nexthop_global,
nexthop_fqdn ? "fqdn" : "ip",
nexthop_fqdn
? nexthop_fqdn
: inet_ntop(
AF_INET6,
&attr->mp_nexthop_global,
buf,
INET6_ADDRSTRLEN));
json_object_string_add(json_nexthop_global,
"afi", "ipv6");
json_object_string_add(json_nexthop_global,
"scope", "global");
} else {
vty_out(vty, " %s",
inet_ntop(AF_INET6,
&attr->mp_nexthop_global, buf,
INET6_ADDRSTRLEN));
nexthop_fqdn
? nexthop_fqdn
: inet_ntop(
AF_INET6,
&attr->mp_nexthop_global,
buf,
INET6_ADDRSTRLEN));
}
}
@ -8391,10 +8459,15 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
if (json_paths) {
json_nexthop_ll = json_object_new_object();
json_object_string_add(
json_nexthop_ll, "ip",
inet_ntop(AF_INET6,
&attr->mp_nexthop_local, buf,
INET6_ADDRSTRLEN));
json_nexthop_ll,
nexthop_fqdn ? "fqdn" : "ip",
nexthop_fqdn
? nexthop_fqdn
: inet_ntop(
AF_INET6,
&attr->mp_nexthop_local,
buf,
INET6_ADDRSTRLEN));
json_object_string_add(json_nexthop_ll, "afi",
"ipv6");
json_object_string_add(json_nexthop_ll, "scope",

View File

@ -0,0 +1,4 @@
router bgp 65000
neighbor 192.168.255.2 remote-as 65001
address-family ipv4 unicast
redistribute connected

View File

@ -0,0 +1,9 @@
!
interface lo
ip address 172.16.255.254/32
!
interface r1-eth0
ip address 192.168.255.1/24
!
ip forwarding
!

View File

@ -0,0 +1,5 @@
router bgp 65001
bgp default show-hostname
neighbor 192.168.255.1 remote-as 65000
address-family ipv4 unicast
redistribute connected

View File

@ -0,0 +1,9 @@
!
interface lo
ip address 172.16.255.253/32
!
interface r2-eth0
ip address 192.168.255.2/24
!
ip forwarding
!

View File

@ -0,0 +1,109 @@
#!/usr/bin/env python
#
# test_bgp_show_ip_bgp_fqdn.py
# Part of NetDEF Topology Tests
#
# Copyright (c) 2019 by
# Network Device Education Foundation, Inc. ("NetDEF")
#
# Permission to use, copy, modify, and/or distribute this software
# for any purpose with or without fee is hereby granted, provided
# that the above copyright notice and this permission notice appear
# in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
# OF THIS SOFTWARE.
#
"""
test_bgp_show_ip_bgp_fqdn.py:
Test if FQND is visible in `show [ip] bgp` output if
`bgp default show-hostname` is toggled.
"""
import os
import sys
import json
import time
import pytest
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, '../'))
# pylint: disable=C0413
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
from mininet.topo import Topo
class TemplateTopo(Topo):
def build(self, *_args, **_opts):
tgen = get_topogen(self)
for routern in range(1, 3):
tgen.add_router('r{}'.format(routern))
switch = tgen.add_switch('s1')
switch.add_link(tgen.gears['r1'])
switch.add_link(tgen.gears['r2'])
def setup_module(mod):
tgen = Topogen(TemplateTopo, mod.__name__)
tgen.start_topology()
router_list = tgen.routers()
for i, (rname, router) in enumerate(router_list.iteritems(), 1):
router.load_config(
TopoRouter.RD_ZEBRA,
os.path.join(CWD, '{}/zebra.conf'.format(rname))
)
router.load_config(
TopoRouter.RD_BGP,
os.path.join(CWD, '{}/bgpd.conf'.format(rname))
)
tgen.start_router()
def teardown_module(mod):
tgen = get_topogen()
tgen.stop_topology()
def test_bgp_maximum_prefix_invalid():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
def _bgp_converge(router, neighbor):
cmd = "show ip bgp neighbor {0} json".format(neighbor)
while True:
output = json.loads(tgen.gears[router].vtysh_cmd(cmd))
if output[neighbor]['bgpState'] == 'Established':
time.sleep(3)
return True
def _bgp_show_nexthop(router, prefix):
cmd = "show ip bgp json"
output = json.loads(tgen.gears[router].vtysh_cmd(cmd))
for nh in output['routes'][prefix][0]['nexthops']:
if 'fqdn' in nh:
return 'fqdn'
return 'ip'
if _bgp_converge('r2', '192.168.255.1'):
assert _bgp_show_nexthop('r2', '172.16.255.254/32') == 'fqdn'
if _bgp_converge('r1', '192.168.255.2'):
assert _bgp_show_nexthop('r1', '172.16.255.253/32') == 'ip'
if __name__ == '__main__':
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))