Skip to content
Permalink
Browse files
bgpd-hostname-cap.patch
bgpd: Exchange hostname capability and display hostnames in outputs

This patch adds a hostname capability. The node's hostname and
domainname are exchanged in the new capability and used in show command
outputs based on a knob enabled by the user. The hostname and domainname
can be a maximum of 64 chars long, each.

Signed-off-by: Dinesh G Dutt <ddutt@cumulusnetworks.com>
Reviewed-by:   Daniel Walton <dwalton@cumulusnetworks.com>
Reviewed-by:   Vivek Venkataraman <vivek@cumulusnetworks.com>
  • Loading branch information
donaldsharp committed May 15, 2015
1 parent 63c5e23 commit 45d4b165b9d01c0e98082e7d1e90a3b1a60b1085
Showing with 353 additions and 23 deletions.
  1. +8 −1 bgpd/bgp_debug.c
  2. +4 −0 bgpd/bgp_fsm.c
  3. +133 −1 bgpd/bgp_open.c
  4. +2 −0 bgpd/bgp_open.h
  5. +65 −11 bgpd/bgp_route.c
  6. +91 −7 bgpd/bgp_vty.c
  7. +40 −2 bgpd/bgpd.c
  8. +10 −1 bgpd/bgpd.h
@@ -183,13 +183,20 @@ bgp_find_peer (struct vty *vty, const char *peer_str)
int ret;
union sockunion su;
struct bgp *bgp;
struct peer *peer;

bgp = vty->index;
ret = str2sockunion (peer_str, &su);

/* 'swpX' string */
if (ret < 0)
return peer_lookup_by_conf_if (bgp, peer_str);
{
peer = peer_lookup_by_conf_if (bgp, peer_str);
if (!peer)
peer = peer_lookup_by_hostname (bgp, peer_str);

return peer;
}
else
return peer_lookup (bgp, &su);
}
@@ -157,6 +157,10 @@ peer_xfer_conn(struct peer *from_peer)
from_peer->last_event = last_evt;
from_peer->last_major_event = last_maj_evt;
peer->remote_id = from_peer->remote_id;
if (from_peer->hostname != NULL)
peer->hostname = XSTRDUP(MTYPE_HOST, from_peer->hostname);
if (from_peer->domainname != NULL)
peer->domainname = XSTRDUP(MTYPE_HOST, from_peer->domainname);

for (afi = AFI_IP; afi < AFI_MAX; afi++)
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
@@ -450,7 +450,86 @@ bgp_capability_addpath (struct peer *peer, struct capability_header *hdr)
return 0;
}

static const struct message capcode_str[] =
static int
bgp_capability_hostname (struct peer *peer, struct capability_header *hdr)
{
struct stream *s = BGP_INPUT (peer);
char str[BGP_MAX_HOSTNAME+1];
size_t end = stream_get_getp (s) + hdr->length;
u_char len;

SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_RCV);

len = stream_getc(s);
if (stream_get_getp(s) + len > end)
{
zlog_warn("%s: Received malformed hostname capability from peer %s",
__FUNCTION__, peer->host);
return -1;
}

if (len > BGP_MAX_HOSTNAME)
{
stream_get(str, s, BGP_MAX_HOSTNAME);
stream_forward_getp(s, len-BGP_MAX_HOSTNAME);
len = BGP_MAX_HOSTNAME; /* to set the '\0' below */
}
else if (len)
stream_get(str, s, len);

if (len)
{
str[len] = '\0';

if (peer->hostname != NULL)
XFREE(MTYPE_HOST, peer->hostname);

if (peer->domainname != NULL)
XFREE(MTYPE_HOST, peer->domainname);

peer->hostname = XSTRDUP(MTYPE_HOST, str);
}

if (stream_get_getp(s) +1 > end)
{
zlog_warn("%s: Received invalid domain name len (hostname capability) from peer %s",
__FUNCTION__, peer->host);
return -1;
}

len = stream_getc(s);
if (stream_get_getp(s) + len > end)
{
zlog_warn("%s: Received runt domain name (hostname capability) from peer %s",
__FUNCTION__, peer->host);
return -1;
}

if (len > BGP_MAX_HOSTNAME)
{
stream_get(str, s, BGP_MAX_HOSTNAME);
stream_forward_getp(s, len-BGP_MAX_HOSTNAME);
len = BGP_MAX_HOSTNAME; /* to set the '\0' below */
}
else if (len)
stream_get(str, s, len);

if (len)
{
str[len] = '\0';
peer->domainname = XSTRDUP(MTYPE_HOST, str);
}

if (bgp_debug_neighbor_events(peer))
{
zlog_debug("%s received hostname %s, domainname %s",
peer->host, peer->hostname, peer->domainname);
}

return 0;
}

static const struct message capcode_str[] =
{
{ CAPABILITY_CODE_MP, "MultiProtocol Extensions" },
{ CAPABILITY_CODE_REFRESH, "Route Refresh" },
@@ -463,6 +542,7 @@ static const struct message capcode_str[] =
{ CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)" },
{ CAPABILITY_CODE_ORF_OLD, "ORF (Old)" },
{ CAPABILITY_CODE_DYNAMIC_OLD, "Dynamic (Old)" },
{ CAPABILITY_CODE_HOSTNAME, "Hostname" },
};
static const int capcode_str_max = array_size(capcode_str);

@@ -480,6 +560,7 @@ static const size_t cap_minsizes[] =
[CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN,
[CAPABILITY_CODE_ORF_OLD] = sizeof (struct capability_orf_entry),
[CAPABILITY_CODE_DYNAMIC_OLD] = CAPABILITY_CODE_DYNAMIC_LEN,
[CAPABILITY_CODE_HOSTNAME] = CAPABILITY_CODE_MIN_HOSTNAME_LEN,
};

/**
@@ -544,6 +625,7 @@ bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability,
case CAPABILITY_CODE_ADDPATH:
case CAPABILITY_CODE_DYNAMIC:
case CAPABILITY_CODE_DYNAMIC_OLD:
case CAPABILITY_CODE_HOSTNAME:
/* Check length. */
if (caphdr.length < cap_minsizes[caphdr.code])
{
@@ -618,6 +700,10 @@ bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability,
if (bgp_capability_addpath (peer, &caphdr))
return -1;
break;
case CAPABILITY_CODE_HOSTNAME:
if (bgp_capability_hostname (peer, &caphdr))
return -1;
break;
default:
if (caphdr.code > 128)
{
@@ -952,6 +1038,7 @@ bgp_open_capability (struct stream *s, struct peer *peer)
as_t local_as;
u_int32_t restart_time;
u_char afi_safi_count = 0;
struct utsname names;

/* Remember current pointer for Opt Parm Len. */
cp = stream_get_endp (s);
@@ -1102,6 +1189,51 @@ bgp_open_capability (struct stream *s, struct peer *peer)
stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN);
}

/* Hostname capability */
uname(&names);
if (names.nodename[0] != '\0')
{
SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV);
stream_putc (s, BGP_OPEN_OPT_CAP);
rcapp = stream_get_endp(s); /* Ptr to length placeholder */
stream_putc(s, 0); /* dummy len for now */
stream_putc (s, CAPABILITY_CODE_HOSTNAME);
capp = stream_get_endp(s);
stream_putc(s, 0); /* dummy len for now */
len = strlen(names.nodename);
if (len > BGP_MAX_HOSTNAME)
len = BGP_MAX_HOSTNAME;

stream_putc(s, len);
stream_put(s, names.nodename, len);
#ifdef _GNU_SOURCE
if ((names.domainname[0] != '\0') &&
(strcmp(names.domainname, "(none)") != 0))
{
len = strlen(names.domainname);
if (len > BGP_MAX_HOSTNAME)
len = BGP_MAX_HOSTNAME;

stream_putc(s, len);
stream_put(s, names.domainname, len);
}
else
#endif
{
stream_putc(s, 0); /* 0 length */
}

/* Set the lengths straight */
len = stream_get_endp(s) - rcapp - 1;
stream_putc_at(s, rcapp, len);
len = stream_get_endp(s) - capp - 1;
stream_putc_at(s, capp, len);

if (bgp_debug_neighbor_events(peer))
zlog_debug("%s Sending hostname cap with hn = %s, dn = %s",
peer->host, names.nodename, names.domainname);
}

/* Sending base graceful-restart capability irrespective of the config */
SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV);
stream_putc (s, BGP_OPEN_OPT_CAP);
@@ -79,6 +79,7 @@ struct capability_gr
#define CAPABILITY_CODE_ADDPATH 69 /* Addpath Capability */
#define CAPABILITY_CODE_REFRESH_OLD 128 /* Route Refresh Capability(cisco) */
#define CAPABILITY_CODE_ORF_OLD 130 /* Cooperative Route Filtering Capability(cisco) */
#define CAPABILITY_CODE_HOSTNAME 131 /* Advertise hostname capabilty */

/* Capability Length */
#define CAPABILITY_CODE_MP_LEN 4
@@ -87,6 +88,7 @@ struct capability_gr
#define CAPABILITY_CODE_RESTART_LEN 2 /* Receiving only case */
#define CAPABILITY_CODE_AS4_LEN 4
#define CAPABILITY_CODE_ADDPATH_LEN 4
#define CAPABILITY_CODE_MIN_HOSTNAME_LEN 2

/* Cooperative Route Filtering Capability. */

@@ -7606,6 +7606,16 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
json_string = json_object_new_string(sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN));
json_object_object_add(json_path, "peer-id", json_string);

if (binfo->peer->hostname)
{
json_string = json_object_new_string(binfo->peer->hostname);
json_object_object_add(json_path, "peer-hostname", json_string);
}
if (binfo->peer->domainname)
{
json_string = json_object_new_string(binfo->peer->domainname);
json_object_object_add(json_path, "peer-domainname", json_string);
}
if (binfo->peer->conf_if)
{
json_string = json_object_new_string(binfo->peer->conf_if);
@@ -7615,9 +7625,23 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
else
{
if (binfo->peer->conf_if)
vty_out (vty, " from %s", binfo->peer->conf_if);
{
if (binfo->peer->hostname &&
bgp_flag_check(binfo->peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
vty_out (vty, " from %s(%s)", binfo->peer->hostname,
binfo->peer->conf_if);
else
vty_out (vty, " from %s", binfo->peer->conf_if);
}
else
vty_out (vty, " from %s", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN));
{
if (binfo->peer->hostname &&
bgp_flag_check(binfo->peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
vty_out (vty, " from %s(%s)", binfo->peer->hostname,
binfo->peer->host);
else
vty_out (vty, " from %s", sockunion2str (&binfo->peer->su, buf, SU_ADDRSTRLEN));
}

if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID))
vty_out (vty, " (%s)", inet_ntoa (attr->extra->originator_id));
@@ -8382,6 +8406,13 @@ route_vty_out_detail_header (struct vty *vty, struct bgp *bgp,
{
if (json)
{
if (peer->hostname)
{
json_string = json_object_new_string(peer->hostname);
json_object_array_add(json_adv_to, json_string);

/* TODO: Have to add domain name here too */
}
if (peer->conf_if)
{
json_string = json_object_new_string(peer->conf_if);
@@ -8397,10 +8428,21 @@ route_vty_out_detail_header (struct vty *vty, struct bgp *bgp,
{
if (! first)
vty_out (vty, " Advertised to non peer-group peers:%s ", VTY_NEWLINE);
if (peer->conf_if)
vty_out (vty, " %s", peer->conf_if);
else
vty_out (vty, " %s", sockunion2str (&peer->su, buf1, SU_ADDRSTRLEN));
if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
{
if (peer->conf_if)
vty_out (vty, " %s(%s)", peer->hostname, peer->conf_if);
else
vty_out (vty, " %s(%s)", peer->hostname,
sockunion2str (&peer->su, buf1, SU_ADDRSTRLEN));
}
else
{
if (peer->conf_if)
vty_out (vty, " %s", peer->conf_if);
else
vty_out (vty, " %s", sockunion2str (&peer->su, buf1, SU_ADDRSTRLEN));
}
}
first = 1;
}
@@ -11513,8 +11555,13 @@ peer_lookup_in_view (struct vty *vty, const char *view_name,
peer = peer_lookup_by_conf_if (bgp, ip_str);
if (!peer)
{
vty_out (vty, "%% Malformed address or name: %s%s", ip_str, VTY_NEWLINE);
return NULL;
/* search for peer by hostname */
peer = peer_lookup_by_hostname(bgp, ip_str);
if (!peer)
{
vty_out (vty, "%% Malformed address or name: %s%s", ip_str, VTY_NEWLINE);
return NULL;
}
}
return peer;
}
@@ -11999,9 +12046,16 @@ bgp_peer_counts (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi)
* on just vty_read()).
*/
thread_execute (bm->master, bgp_peer_count_walker, &pcounts, 0);

vty_out (vty, "Prefix counts for %s, %s%s",
peer->host, afi_safi_print (afi, safi), VTY_NEWLINE);

if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME))
{
vty_out (vty, "Prefix counts for %s/%s, %s%s",
peer->hostname, peer->host, afi_safi_print (afi, safi),
VTY_NEWLINE);
}
else
vty_out (vty, "Prefix counts for %s, %s%s",
peer->host, afi_safi_print (afi, safi), VTY_NEWLINE);
vty_out (vty, "PfxCt: %ld%s", peer->pcount[afi][safi], VTY_NEWLINE);
vty_out (vty, "%sCounts from RIB table walk:%s%s",
VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);

0 comments on commit 45d4b16

Please sign in to comment.