mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-07-04 19:09:47 +00:00
bmp: add a interface source to bmp connect command
With current release, forcin the source ip address when setting up a BMP connection is not possible. The need is to add an extra parameter for the following vty command: router bgp 65500 bmp targets AAA bmp connect 2.2.2.2 port 666 min-retry 100 max-retry 700 bmp connect 2:2::2:2 port 666 min-retry 100 max-retry 700 [source-interface lo1] Signed-off-by: Francois Dumontet <francois.dumontet@6wind.com>
This commit is contained in:
parent
23a1220847
commit
09f267ec95
103
bgpd/bgp_bmp.c
103
bgpd/bgp_bmp.c
@ -50,6 +50,7 @@
|
|||||||
#include "bgpd/bgp_updgrp.h"
|
#include "bgpd/bgp_updgrp.h"
|
||||||
#include "bgpd/bgp_vty.h"
|
#include "bgpd/bgp_vty.h"
|
||||||
#include "bgpd/bgp_trace.h"
|
#include "bgpd/bgp_trace.h"
|
||||||
|
#include "bgpd/bgp_network.h"
|
||||||
|
|
||||||
static void bmp_close(struct bmp *bmp);
|
static void bmp_close(struct bmp *bmp);
|
||||||
static struct bmp_bgp *bmp_bgp_find(struct bgp *bgp);
|
static struct bmp_bgp *bmp_bgp_find(struct bgp *bgp);
|
||||||
@ -1763,6 +1764,7 @@ static void bmp_active_put(struct bmp_active *ba)
|
|||||||
if (ba->socket != -1)
|
if (ba->socket != -1)
|
||||||
close(ba->socket);
|
close(ba->socket);
|
||||||
|
|
||||||
|
XFREE(MTYPE_TMP, ba->ifsrc);
|
||||||
XFREE(MTYPE_TMP, ba->hostname);
|
XFREE(MTYPE_TMP, ba->hostname);
|
||||||
XFREE(MTYPE_BMP_ACTIVE, ba);
|
XFREE(MTYPE_BMP_ACTIVE, ba);
|
||||||
}
|
}
|
||||||
@ -1773,8 +1775,37 @@ static void bmp_active_connect(struct bmp_active *ba)
|
|||||||
{
|
{
|
||||||
enum connect_result res;
|
enum connect_result res;
|
||||||
char buf[SU_ADDRSTRLEN];
|
char buf[SU_ADDRSTRLEN];
|
||||||
|
struct interface *ifp;
|
||||||
|
vrf_id_t vrf_id = VRF_DEFAULT;
|
||||||
|
int res_bind;
|
||||||
|
|
||||||
for (; ba->addrpos < ba->addrtotal; ba->addrpos++) {
|
for (; ba->addrpos < ba->addrtotal; ba->addrpos++) {
|
||||||
|
if (ba->ifsrc) {
|
||||||
|
if (ba->targets && ba->targets->bgp)
|
||||||
|
vrf_id = ba->targets->bgp->vrf_id;
|
||||||
|
|
||||||
|
/* find interface and related */
|
||||||
|
/* address with same family */
|
||||||
|
ifp = if_lookup_by_name(ba->ifsrc, vrf_id);
|
||||||
|
if (!ifp) {
|
||||||
|
zlog_warn("bmp[%s]: failed to find interface",
|
||||||
|
ba->ifsrc);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bgp_update_address(ifp, &ba->addrs[ba->addrpos],
|
||||||
|
&ba->addrsrc)){
|
||||||
|
zlog_warn("bmp[%s]: failed to find matching address",
|
||||||
|
ba->ifsrc);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
zlog_info("bmp[%s]: selected source address : %s",
|
||||||
|
ba->ifsrc,
|
||||||
|
sockunion2str(&ba->addrsrc,
|
||||||
|
buf,
|
||||||
|
SU_ADDRSTRLEN));
|
||||||
|
}
|
||||||
|
|
||||||
ba->socket = sockunion_socket(&ba->addrs[ba->addrpos]);
|
ba->socket = sockunion_socket(&ba->addrs[ba->addrpos]);
|
||||||
if (ba->socket < 0) {
|
if (ba->socket < 0) {
|
||||||
zlog_warn("bmp[%s]: failed to create socket",
|
zlog_warn("bmp[%s]: failed to create socket",
|
||||||
@ -1783,6 +1814,23 @@ static void bmp_active_connect(struct bmp_active *ba)
|
|||||||
}
|
}
|
||||||
|
|
||||||
set_nonblocking(ba->socket);
|
set_nonblocking(ba->socket);
|
||||||
|
|
||||||
|
if (!sockunion_is_null(&ba->addrsrc)) {
|
||||||
|
res_bind = sockunion_bind(ba->socket, &ba->addrsrc, 0,
|
||||||
|
&ba->addrsrc);
|
||||||
|
if (res_bind < 0) {
|
||||||
|
sockunion2str(&ba->addrsrc, buf, sizeof(buf));
|
||||||
|
zlog_warn(
|
||||||
|
"bmp[%s]: no bind currently to source address %s:%d",
|
||||||
|
ba->hostname, buf, ba->port);
|
||||||
|
close(ba->socket);
|
||||||
|
ba->socket = -1;
|
||||||
|
sockunion_init(&ba->addrsrc);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
res = sockunion_connect(ba->socket, &ba->addrs[ba->addrpos],
|
res = sockunion_connect(ba->socket, &ba->addrs[ba->addrpos],
|
||||||
htons(ba->port), 0);
|
htons(ba->port), 0);
|
||||||
switch (res) {
|
switch (res) {
|
||||||
@ -1793,10 +1841,19 @@ static void bmp_active_connect(struct bmp_active *ba)
|
|||||||
ba->hostname, buf, ba->port);
|
ba->hostname, buf, ba->port);
|
||||||
close(ba->socket);
|
close(ba->socket);
|
||||||
ba->socket = -1;
|
ba->socket = -1;
|
||||||
|
sockunion_init(&ba->addrsrc);
|
||||||
continue;
|
continue;
|
||||||
case connect_success:
|
case connect_success:
|
||||||
|
sockunion2str(&ba->addrs[ba->addrpos], buf,
|
||||||
|
sizeof(buf));
|
||||||
|
zlog_info("bmp[%s]: connected to %s:%d",
|
||||||
|
ba->hostname, buf, ba->port);
|
||||||
break;
|
break;
|
||||||
case connect_in_progress:
|
case connect_in_progress:
|
||||||
|
sockunion2str(&ba->addrs[ba->addrpos], buf,
|
||||||
|
sizeof(buf));
|
||||||
|
zlog_warn("bmp[%s]: connect in progress %s:%d",
|
||||||
|
ba->hostname, buf, ba->port);
|
||||||
bmp_active_setup(ba);
|
bmp_active_setup(ba);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2041,7 +2098,7 @@ DEFPY(no_bmp_listener_main,
|
|||||||
|
|
||||||
DEFPY(bmp_connect,
|
DEFPY(bmp_connect,
|
||||||
bmp_connect_cmd,
|
bmp_connect_cmd,
|
||||||
"[no] bmp connect HOSTNAME port (1-65535) {min-retry (100-86400000)|max-retry (100-86400000)}",
|
"[no] bmp connect HOSTNAME port (1-65535) {min-retry (100-86400000)|max-retry (100-86400000)} [source-interface <WORD$srcif>]",
|
||||||
NO_STR
|
NO_STR
|
||||||
BMP_STR
|
BMP_STR
|
||||||
"Actively establish connection to monitoring station\n"
|
"Actively establish connection to monitoring station\n"
|
||||||
@ -2051,7 +2108,9 @@ DEFPY(bmp_connect,
|
|||||||
"Minimum connection retry interval\n"
|
"Minimum connection retry interval\n"
|
||||||
"Minimum connection retry interval (milliseconds)\n"
|
"Minimum connection retry interval (milliseconds)\n"
|
||||||
"Maximum connection retry interval\n"
|
"Maximum connection retry interval\n"
|
||||||
"Maximum connection retry interval (milliseconds)\n")
|
"Maximum connection retry interval (milliseconds)\n"
|
||||||
|
"Source interface to use\n"
|
||||||
|
"Define an interface\n")
|
||||||
{
|
{
|
||||||
VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
|
VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
|
||||||
struct bmp_active *ba;
|
struct bmp_active *ba;
|
||||||
@ -2062,11 +2121,21 @@ DEFPY(bmp_connect,
|
|||||||
vty_out(vty, "%% No such active connection found\n");
|
vty_out(vty, "%% No such active connection found\n");
|
||||||
return CMD_WARNING;
|
return CMD_WARNING;
|
||||||
}
|
}
|
||||||
|
/* connection deletion need same hostname port and interface */
|
||||||
|
if (ba->ifsrc || srcif)
|
||||||
|
if ((!ba->ifsrc) || (!srcif) ||
|
||||||
|
!strcmp(ba->ifsrc, srcif)) {
|
||||||
|
vty_out(vty,
|
||||||
|
"%% No such active connection found\n");
|
||||||
|
return CMD_WARNING;
|
||||||
|
}
|
||||||
bmp_active_put(ba);
|
bmp_active_put(ba);
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ba = bmp_active_get(bt, hostname, port);
|
ba = bmp_active_get(bt, hostname, port);
|
||||||
|
if (srcif)
|
||||||
|
ba->ifsrc = XSTRDUP(MTYPE_TMP, srcif);
|
||||||
if (min_retry_str)
|
if (min_retry_str)
|
||||||
ba->minretry = min_retry;
|
ba->minretry = min_retry;
|
||||||
if (max_retry_str)
|
if (max_retry_str)
|
||||||
@ -2309,7 +2378,7 @@ DEFPY(show_bmp,
|
|||||||
|
|
||||||
vty_out(vty, "\n Outbound connections:\n");
|
vty_out(vty, "\n Outbound connections:\n");
|
||||||
tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
|
tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
|
||||||
ttable_add_row(tt, "remote|state||timer");
|
ttable_add_row(tt, "remote|state||timer|local");
|
||||||
ttable_rowseps(tt, 0, BOTTOM, true, '-');
|
ttable_rowseps(tt, 0, BOTTOM, true, '-');
|
||||||
frr_each (bmp_actives, &bt->actives, ba) {
|
frr_each (bmp_actives, &bt->actives, ba) {
|
||||||
const char *state_str = "?";
|
const char *state_str = "?";
|
||||||
@ -2318,9 +2387,13 @@ DEFPY(show_bmp,
|
|||||||
peer_uptime(ba->bmp->t_up.tv_sec,
|
peer_uptime(ba->bmp->t_up.tv_sec,
|
||||||
uptime, sizeof(uptime),
|
uptime, sizeof(uptime),
|
||||||
false, NULL);
|
false, NULL);
|
||||||
ttable_add_row(tt, "%s:%d|Up|%s|%s",
|
ttable_add_row(tt, "%s:%d|Up|%s|%s|%s",
|
||||||
ba->hostname, ba->port,
|
ba->hostname, ba->port,
|
||||||
ba->bmp->remote, uptime);
|
ba->bmp->remote, uptime,
|
||||||
|
sockunion2str(
|
||||||
|
&ba->addrsrc,
|
||||||
|
buf,
|
||||||
|
SU_ADDRSTRLEN));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2340,11 +2413,15 @@ DEFPY(show_bmp,
|
|||||||
state_str = "Resolving";
|
state_str = "Resolving";
|
||||||
}
|
}
|
||||||
|
|
||||||
ttable_add_row(tt, "%s:%d|%s|%s|%s",
|
sockunion2str(&ba->addrsrc,
|
||||||
|
buf,
|
||||||
|
SU_ADDRSTRLEN);
|
||||||
|
ttable_add_row(tt, "%s:%d|%s|%s|%s|%s",
|
||||||
ba->hostname, ba->port,
|
ba->hostname, ba->port,
|
||||||
state_str,
|
state_str,
|
||||||
ba->last_err ? ba->last_err : "",
|
ba->last_err ? ba->last_err : "",
|
||||||
uptime);
|
uptime,
|
||||||
|
buf);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
out = ttable_dump(tt, "\n");
|
out = ttable_dump(tt, "\n");
|
||||||
@ -2432,10 +2509,16 @@ static int bmp_config_write(struct bgp *bgp, struct vty *vty)
|
|||||||
sockunion2str(&bl->addr, buf, SU_ADDRSTRLEN),
|
sockunion2str(&bl->addr, buf, SU_ADDRSTRLEN),
|
||||||
bl->port);
|
bl->port);
|
||||||
|
|
||||||
frr_each (bmp_actives, &bt->actives, ba)
|
frr_each (bmp_actives, &bt->actives, ba) {
|
||||||
vty_out(vty, " bmp connect %s port %u min-retry %u max-retry %u\n",
|
vty_out(vty, " bmp connect %s port %u min-retry %u max-retry %u",
|
||||||
ba->hostname, ba->port, ba->minretry, ba->maxretry);
|
ba->hostname, ba->port,
|
||||||
|
ba->minretry, ba->maxretry);
|
||||||
|
|
||||||
|
if (ba->ifsrc)
|
||||||
|
vty_out(vty, " source-interface %s\n", ba->ifsrc);
|
||||||
|
else
|
||||||
|
vty_out(vty, "\n");
|
||||||
|
}
|
||||||
vty_out(vty, " exit\n");
|
vty_out(vty, " exit\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,6 +179,8 @@ struct bmp_active {
|
|||||||
char *hostname;
|
char *hostname;
|
||||||
int port;
|
int port;
|
||||||
unsigned minretry, maxretry;
|
unsigned minretry, maxretry;
|
||||||
|
char *ifsrc;
|
||||||
|
union sockunion addrsrc;
|
||||||
|
|
||||||
struct resolver_query resq;
|
struct resolver_query resq;
|
||||||
|
|
||||||
|
@ -632,7 +632,7 @@ static char *bgp_get_bound_name(struct peer *peer)
|
|||||||
return peer->bgp->name;
|
return peer->bgp->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bgp_update_address(struct interface *ifp, const union sockunion *dst,
|
int bgp_update_address(struct interface *ifp, const union sockunion *dst,
|
||||||
union sockunion *addr)
|
union sockunion *addr)
|
||||||
{
|
{
|
||||||
struct prefix *p, *sel, d;
|
struct prefix *p, *sel, d;
|
||||||
|
@ -45,5 +45,7 @@ extern int bgp_md5_unset_prefix(struct bgp *bgp, struct prefix *p);
|
|||||||
extern int bgp_md5_set(struct peer *);
|
extern int bgp_md5_set(struct peer *);
|
||||||
extern int bgp_md5_unset(struct peer *);
|
extern int bgp_md5_unset(struct peer *);
|
||||||
extern int bgp_set_socket_ttl(struct peer *, int fd);
|
extern int bgp_set_socket_ttl(struct peer *, int fd);
|
||||||
|
extern int bgp_update_address(struct interface *ifp, const union sockunion *dst,
|
||||||
|
union sockunion *addr);
|
||||||
|
|
||||||
#endif /* _QUAGGA_BGP_NETWORK_H */
|
#endif /* _QUAGGA_BGP_NETWORK_H */
|
||||||
|
@ -108,13 +108,15 @@ BMP session configuration
|
|||||||
Inside a ``bmp targets`` block, the following commands control session
|
Inside a ``bmp targets`` block, the following commands control session
|
||||||
establishment:
|
establishment:
|
||||||
|
|
||||||
.. clicmd:: bmp connect HOSTNAME port (1-65535) {min-retry MSEC|max-retry MSEC}
|
|
||||||
|
.. clicmd:: bmp connect HOSTNAME port (1-65535) {min-retry MSEC|max-retry MSEC} [source-interface WORD]
|
||||||
|
|
||||||
Add/remove an active outbound BMP session. HOSTNAME is resolved via DNS,
|
Add/remove an active outbound BMP session. HOSTNAME is resolved via DNS,
|
||||||
if multiple addresses are returned they are tried in nondeterministic
|
if multiple addresses are returned they are tried in nondeterministic
|
||||||
order. Only one connection will be established even if multiple addresses
|
order. Only one connection will be established even if multiple addresses
|
||||||
are returned. ``min-retry`` and ``max-retry`` specify (in milliseconds)
|
are returned. ``min-retry`` and ``max-retry`` specify (in milliseconds)
|
||||||
bounds for exponential backoff.
|
bounds for exponential backoff. ``source-interface`` is the local interface on
|
||||||
|
which the connection has to bind.
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user