mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-14 04:26:12 +00:00
bgpd-interface-ipv4-cmd.patch
BGP: Determine peer's IP address if interface has /30, /31 Allow interface-based session config for IPv4 numbered links if the link address is either /30 or /31. This is not RFC5549, but can be deployed now, and independent of whether the peer supports RFC5549 or not. Signed-off-by: Dinesh G Dutt <ddutt@cumulusnetworks.com> Reviewed-By: Vivek Venkataram <vivek@cumulusnetworks.com>
This commit is contained in:
parent
b9d9b73d58
commit
8ffedceac3
@ -41,6 +41,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
#include "bgpd/bgp_nht.h"
|
||||
#include "bgpd/bgp_debug.h"
|
||||
#include "bgpd/bgp_damp.h"
|
||||
#include "bgpd/bgp_fsm.h"
|
||||
#include "zebra/rib.h"
|
||||
#include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */
|
||||
|
||||
@ -204,6 +205,10 @@ bgp_connected_add (struct connected *ifc)
|
||||
struct prefix *addr;
|
||||
struct bgp_node *rn;
|
||||
struct bgp_connected_ref *bc;
|
||||
struct listnode *node, *nnode, *mnode;
|
||||
struct bgp *bgp;
|
||||
struct peer *peer;
|
||||
u_int32_t saddr;
|
||||
|
||||
addr = ifc->address;
|
||||
|
||||
@ -229,6 +234,20 @@ bgp_connected_add (struct connected *ifc)
|
||||
bc->refcnt = 1;
|
||||
rn->info = bc;
|
||||
}
|
||||
|
||||
for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp))
|
||||
{
|
||||
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
|
||||
{
|
||||
if (peer->conf_if && (strcmp (peer->conf_if, ifc->ifp->name) == 0) &&
|
||||
!CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
|
||||
{
|
||||
if (peer_active(peer))
|
||||
BGP_EVENT_ADD (peer, BGP_Stop);
|
||||
BGP_EVENT_ADD (peer, BGP_Start);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else if (addr->family == AF_INET6)
|
||||
|
@ -2611,10 +2611,11 @@ DEFUN (neighbor_remote_as,
|
||||
|
||||
DEFUN (neighbor_interface_config,
|
||||
neighbor_interface_config_cmd,
|
||||
"neighbor WORD interface",
|
||||
"neighbor WORD interface {v6only}",
|
||||
NEIGHBOR_STR
|
||||
"Interface name or neighbor tag\n"
|
||||
"Enable BGP on interface\n")
|
||||
"Enable BGP on interface\n"
|
||||
"Enable BGP with v6 link-local only\n")
|
||||
{
|
||||
struct bgp *bgp;
|
||||
struct peer *peer;
|
||||
@ -2628,7 +2629,10 @@ DEFUN (neighbor_interface_config,
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
peer = peer_conf_interface_get (bgp, argv[0], AFI_IP, SAFI_UNICAST);
|
||||
if (argv[1] != NULL)
|
||||
peer = peer_conf_interface_get (bgp, argv[0], AFI_IP, SAFI_UNICAST, 1);
|
||||
else
|
||||
peer = peer_conf_interface_get (bgp, argv[0], AFI_IP, SAFI_UNICAST, 0);
|
||||
if (!peer)
|
||||
return CMD_WARNING;
|
||||
|
||||
@ -4979,12 +4983,15 @@ DEFUN (neighbor_interface,
|
||||
"Interface\n"
|
||||
"Interface name\n")
|
||||
{
|
||||
return peer_interface_vty (vty, argv[0], argv[1]);
|
||||
if (argc == 3)
|
||||
return peer_interface_vty (vty, argv[0], argv[1]);
|
||||
else
|
||||
return peer_interface_vty (vty, argv[0], argv[1]);
|
||||
}
|
||||
|
||||
DEFUN (no_neighbor_interface,
|
||||
no_neighbor_interface_cmd,
|
||||
NO_NEIGHBOR_CMD "interface WORD",
|
||||
NO_NEIGHBOR_CMD2 "interface WORD",
|
||||
NO_STR
|
||||
NEIGHBOR_STR
|
||||
NEIGHBOR_ADDR_STR
|
||||
|
124
bgpd/bgpd.c
124
bgpd/bgpd.c
@ -782,6 +782,9 @@ peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
|
||||
static void
|
||||
peer_global_config_reset (struct peer *peer)
|
||||
{
|
||||
|
||||
int v6only;
|
||||
|
||||
peer->weight = 0;
|
||||
peer->change_local_as = 0;
|
||||
peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
|
||||
@ -801,7 +804,14 @@ peer_global_config_reset (struct peer *peer)
|
||||
else
|
||||
peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
|
||||
|
||||
/* This is a per-peer specific flag and so we must preserve it */
|
||||
v6only = CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
|
||||
|
||||
peer->flags = 0;
|
||||
|
||||
if (v6only)
|
||||
SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
|
||||
|
||||
peer->config = 0;
|
||||
peer->holdtime = 0;
|
||||
peer->keepalive = 0;
|
||||
@ -1163,30 +1173,74 @@ void
|
||||
bgp_peer_conf_if_to_su_update (struct peer *peer)
|
||||
{
|
||||
struct interface *ifp;
|
||||
struct nbr_connected *ifc;
|
||||
struct nbr_connected *ifc_nbr;
|
||||
struct connected *ifc;
|
||||
struct prefix p;
|
||||
u_int32_t s_addr;
|
||||
struct listnode *node;
|
||||
|
||||
if (!peer->conf_if)
|
||||
return;
|
||||
|
||||
if ((ifp = if_lookup_by_name(peer->conf_if)) &&
|
||||
ifp->nbr_connected &&
|
||||
(ifc = listnode_head(ifp->nbr_connected)))
|
||||
if (ifp = if_lookup_by_name(peer->conf_if))
|
||||
{
|
||||
peer->su.sa.sa_family = AF_INET6;
|
||||
memcpy(&peer->su.sin6.sin6_addr, &ifc->address->u.prefix,
|
||||
sizeof (struct in6_addr));
|
||||
/* if multiple IP addresses assigned to link, we pick the first */
|
||||
if (!CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
|
||||
for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc))
|
||||
if (ifc->address && (ifc->address->family == AF_INET))
|
||||
{
|
||||
/* Try IPv4 connection first, if present */
|
||||
PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
|
||||
/* We can determine peer's IP address if prefixlen is 30/31 */
|
||||
if (p.prefixlen == 30)
|
||||
{
|
||||
peer->su.sa.sa_family = AF_INET;
|
||||
s_addr = ntohl(p.u.prefix4.s_addr);
|
||||
if (s_addr % 4 == 1)
|
||||
peer->su.sin.sin_addr.s_addr = htonl(s_addr+1);
|
||||
else if (s_addr % 4 == 2)
|
||||
peer->su.sin.sin_addr.s_addr = htonl(s_addr-1);
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
||||
peer->su->sin.sin_len = sizeof(struct sockaddr_in);
|
||||
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
|
||||
return;
|
||||
}
|
||||
else if (p.prefixlen == 31)
|
||||
{
|
||||
peer->su.sa.sa_family = AF_INET;
|
||||
s_addr = ntohl(p.u.prefix4.s_addr);
|
||||
if (s_addr % 2 == 0)
|
||||
peer->su.sin.sin_addr.s_addr = htonl(s_addr+1);
|
||||
else
|
||||
peer->su.sin.sin_addr.s_addr = htonl(s_addr-1);
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
||||
peer->su->sin.sin_len = sizeof(struct sockaddr_in);
|
||||
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
|
||||
return;
|
||||
}
|
||||
else
|
||||
zlog_warn("%s neighbor interface with IPv4 numbered links used without /30 or /31",
|
||||
peer->conf_if);
|
||||
}
|
||||
|
||||
if (ifp->nbr_connected &&
|
||||
(ifc_nbr = listnode_head(ifp->nbr_connected)))
|
||||
{
|
||||
peer->su.sa.sa_family = AF_INET6;
|
||||
memcpy(&peer->su.sin6.sin6_addr, &ifc_nbr->address->u.prefix,
|
||||
sizeof (struct in6_addr));
|
||||
#ifdef SIN6_LEN
|
||||
peer->su.sin6.sin6_len = sizeof (struct sockaddr_in6);
|
||||
peer->su.sin6.sin6_len = sizeof (struct sockaddr_in6);
|
||||
#endif
|
||||
peer->su.sin6.sin6_scope_id = ifp->ifindex;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This works as an indication of unresolved peer address
|
||||
on a BGP interface*/
|
||||
peer->su.sa.sa_family = AF_UNSPEC;
|
||||
memset(&peer->su.sin6.sin6_addr, 0, sizeof (struct in6_addr));
|
||||
peer->su.sin6.sin6_scope_id = ifp->ifindex;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* This works as an indication of unresolved peer address
|
||||
on a BGP interface*/
|
||||
peer->su.sa.sa_family = AF_UNSPEC;
|
||||
memset(&peer->su.sin6.sin6_addr, 0, sizeof (struct in6_addr));
|
||||
}
|
||||
|
||||
/* Create new BGP peer. */
|
||||
@ -1255,7 +1309,7 @@ peer_create (union sockunion *su, const char *conf_if, struct bgp *bgp,
|
||||
|
||||
struct peer *
|
||||
peer_conf_interface_get(struct bgp *bgp, const char *conf_if, afi_t afi,
|
||||
safi_t safi)
|
||||
safi_t safi, int v6only)
|
||||
{
|
||||
struct peer *peer;
|
||||
|
||||
@ -1268,6 +1322,26 @@ peer_conf_interface_get(struct bgp *bgp, const char *conf_if, afi_t afi,
|
||||
else
|
||||
peer = peer_create (NULL, conf_if, bgp, bgp->as, AS_SPECIFIED, 0, afi, safi);
|
||||
|
||||
if (peer && v6only)
|
||||
SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
|
||||
}
|
||||
else if ((v6only && !CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)) ||
|
||||
(!v6only && CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY)))
|
||||
{
|
||||
if (v6only)
|
||||
SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
|
||||
else
|
||||
UNSET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
|
||||
|
||||
/* v6only flag changed. Reset bgp seesion */
|
||||
if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
|
||||
{
|
||||
peer->last_reset = PEER_DOWN_V6ONLY_CHANGE;
|
||||
bgp_notify_send (peer, BGP_NOTIFY_CEASE,
|
||||
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
|
||||
}
|
||||
else
|
||||
bgp_session_reset(peer);
|
||||
}
|
||||
|
||||
return peer;
|
||||
@ -1845,6 +1919,7 @@ peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
|
||||
struct peer *conf;
|
||||
struct bgp_filter *pfilter;
|
||||
struct bgp_filter *gfilter;
|
||||
int v6only;
|
||||
|
||||
conf = group->conf;
|
||||
pfilter = &peer->filter[afi][safi];
|
||||
@ -1867,8 +1942,15 @@ peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
|
||||
/* Weight */
|
||||
peer->weight = conf->weight;
|
||||
|
||||
/* this flag is per-neighbor and so has to be preserved */
|
||||
v6only = CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
|
||||
|
||||
/* peer flags apply */
|
||||
peer->flags = conf->flags;
|
||||
|
||||
if (v6only)
|
||||
SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
|
||||
|
||||
/* peer af_flags apply */
|
||||
peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
|
||||
/* peer config apply */
|
||||
@ -2446,6 +2528,7 @@ peer_group_unbind (struct bgp *bgp, struct peer *peer,
|
||||
struct peer_group *group, afi_t afi, safi_t safi)
|
||||
{
|
||||
struct peer *other;
|
||||
int v6only;
|
||||
|
||||
if (! peer->af_group[afi][safi])
|
||||
return 0;
|
||||
@ -5918,7 +6001,12 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
|
||||
if (afi == AFI_IP && safi == SAFI_UNICAST)
|
||||
{
|
||||
if (peer->conf_if)
|
||||
vty_out (vty, " neighbor %s interface%s", addr, VTY_NEWLINE);
|
||||
{
|
||||
if (CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
|
||||
vty_out (vty, " neighbor %s interface v6only %s", addr, VTY_NEWLINE);
|
||||
else
|
||||
vty_out (vty, " neighbor %s interface%s", addr, VTY_NEWLINE);
|
||||
}
|
||||
|
||||
/* remote-as. */
|
||||
if (! peer_group_active (peer))
|
||||
|
@ -614,6 +614,7 @@ struct peer
|
||||
#define PEER_FLAG_LONESOUL (1 << 12)
|
||||
#define PEER_FLAG_DYNAMIC_NEIGHBOR (1 << 13) /* dynamic neighbor */
|
||||
#define PEER_FLAG_CAPABILITY_ENHE (1 << 14) /* Extended next-hop (rfc 5549)*/
|
||||
#define PEER_FLAG_IFPEER_V6ONLY (1 << 15) /* if-based peer is v6 only *
|
||||
|
||||
/* NSF mode (graceful restart) */
|
||||
u_char nsf[AFI_MAX][SAFI_MAX];
|
||||
@ -677,6 +678,7 @@ struct peer
|
||||
#define PEER_CONFIG_TIMER (1 << 1) /* keepalive & holdtime */
|
||||
#define PEER_CONFIG_CONNECT (1 << 2) /* connect */
|
||||
#define PEER_CONFIG_ROUTEADV (1 << 3) /* route advertise */
|
||||
|
||||
u_int32_t weight;
|
||||
u_int32_t holdtime;
|
||||
u_int32_t keepalive;
|
||||
@ -796,6 +798,7 @@ struct peer
|
||||
#define PEER_DOWN_PASSIVE_CHANGE 20 /* neighbor passive command */
|
||||
#define PEER_DOWN_MULTIHOP_CHANGE 21 /* neighbor multihop command */
|
||||
#define PEER_DOWN_NSF_CLOSE_SESSION 22 /* NSF tcp session close */
|
||||
#define PEER_DOWN_V6ONLY_CHANGE 23 /* if-based peering v6only toggled */
|
||||
unsigned long last_reset_cause_size;
|
||||
u_char last_reset_cause[BGP_MAX_PACKET_SIZE];
|
||||
|
||||
@ -1111,7 +1114,7 @@ extern struct bgp *bgp_lookup_by_name (const char *);
|
||||
extern struct peer *peer_lookup (struct bgp *, union sockunion *);
|
||||
extern struct peer *peer_lookup_by_conf_if (struct bgp *, const char *);
|
||||
extern struct peer *peer_conf_interface_get(struct bgp *, const char *, afi_t,
|
||||
safi_t);
|
||||
safi_t, int v6only);
|
||||
extern void bgp_peer_conf_if_to_su_update (struct peer *);
|
||||
extern int peer_group_listen_range_del(struct peer_group *, struct prefix *);
|
||||
extern struct peer_group *peer_group_lookup (struct bgp *, const char *);
|
||||
|
Loading…
Reference in New Issue
Block a user