bgpd: make _vpnv4 static handling SAFI-agnostic

This changes the existing _vpnv4 functions for MPLS-VPN into
SAFI-agnostic functions, renaming them from *_vpnv4 to *_safi.

Also adds route-map support while at it.

Signed-off-by: Lou Berger <lberger@labn.net>
Reviewed-by: David Lamparter <equinox@opensourcerouting.org>
(cherry picked from commit a76d9ca3584c1751a592457c167c1e146648ceb6)

Conflicts:
	bgpd/bgp_route.c
This commit is contained in:
Lou Berger 2016-01-12 13:41:53 -05:00 committed by vivek
parent bcd9fa7ff2
commit 137446f997
3 changed files with 184 additions and 55 deletions

View File

@ -340,7 +340,22 @@ DEFUN (vpnv4_network,
"BGP tag\n"
"tag value\n")
{
return bgp_static_set_vpnv4 (vty, argv[0], argv[1], argv[2]);
return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[0], argv[1], argv[2], NULL);
}
DEFUN (vpnv4_network_route_map,
vpnv4_network_route_map_cmd,
"network A.B.C.D/M rd ASN:nn_or_IP-address:nn tag WORD route-map WORD",
"Specify a network to announce via BGP\n"
"IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
"Specify Route Distinguisher\n"
"VPN Route Distinguisher\n"
"BGP tag\n"
"tag value\n"
"route map\n"
"route map name\n")
{
return bgp_static_set_safi (SAFI_MPLS_VPN, vty, argv[0], argv[1], argv[2], argv[3]);
}
/* For testing purpose, static route of MPLS-VPN. */
@ -355,7 +370,7 @@ DEFUN (no_vpnv4_network,
"BGP tag\n"
"tag value\n")
{
return bgp_static_unset_vpnv4 (vty, argv[0], argv[1], argv[2]);
return bgp_static_unset_safi (SAFI_MPLS_VPN, vty, argv[0], argv[1], argv[2]);
}
static int
@ -1020,6 +1035,7 @@ void
bgp_mplsvpn_init (void)
{
install_element (BGP_VPNV4_NODE, &vpnv4_network_cmd);
install_element (BGP_VPNV4_NODE, &vpnv4_network_route_map_cmd);
install_element (BGP_VPNV4_NODE, &no_vpnv4_network_cmd);

View File

@ -3476,36 +3476,6 @@ bgp_static_update (struct bgp *bgp, struct prefix *p,
bgp_static_update_main (bgp, p, bgp_static, afi, safi);
}
static void
bgp_static_update_vpnv4 (struct bgp *bgp, struct prefix *p, afi_t afi,
safi_t safi, struct prefix_rd *prd, u_char *tag)
{
struct bgp_node *rn;
struct bgp_info *new;
rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, prd);
/* Make new BGP info. */
new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
bgp_attr_default_intern(BGP_ORIGIN_IGP), rn);
SET_FLAG (new->flags, BGP_INFO_VALID);
new->extra = bgp_info_extra_new();
memcpy (new->extra->tag, tag, 3);
/* Aggregate address increment. */
bgp_aggregate_increment (bgp, p, new, afi, safi);
/* Register new BGP information. */
bgp_info_add (rn, new);
/* route_node_get lock */
bgp_unlock_node (rn);
/* Process change. */
bgp_process (bgp, rn, afi, safi);
}
void
bgp_static_withdraw (struct bgp *bgp, struct prefix *p, afi_t afi,
safi_t safi)
@ -3535,9 +3505,12 @@ bgp_static_withdraw (struct bgp *bgp, struct prefix *p, afi_t afi,
bgp_unlock_node (rn);
}
/*
* Used for SAFI_MPLS_VPN and SAFI_ENCAP
*/
static void
bgp_static_withdraw_vpnv4 (struct bgp *bgp, struct prefix *p, afi_t afi,
safi_t safi, struct prefix_rd *prd, u_char *tag)
bgp_static_withdraw_safi (struct bgp *bgp, struct prefix *p, afi_t afi,
safi_t safi, struct prefix_rd *prd, u_char *tag)
{
struct bgp_node *rn;
struct bgp_info *ri;
@ -3563,6 +3536,127 @@ bgp_static_withdraw_vpnv4 (struct bgp *bgp, struct prefix *p, afi_t afi,
bgp_unlock_node (rn);
}
static void
bgp_static_update_safi (struct bgp *bgp, struct prefix *p,
struct bgp_static *bgp_static, afi_t afi, safi_t safi)
{
struct bgp_node *rn;
struct bgp_info *new;
struct attr *attr_new;
struct attr attr = { 0 };
struct bgp_info *ri;
assert (bgp_static);
rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, &bgp_static->prd);
bgp_attr_default_set (&attr, BGP_ORIGIN_IGP);
attr.nexthop = bgp_static->igpnexthop;
attr.med = bgp_static->igpmetric;
attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC);
/* Apply route-map. */
if (bgp_static->rmap.name)
{
struct attr attr_tmp = attr;
struct bgp_info info;
int ret;
info.peer = bgp->peer_self;
info.attr = &attr_tmp;
SET_FLAG (bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK);
ret = route_map_apply (bgp_static->rmap.map, p, RMAP_BGP, &info);
bgp->peer_self->rmap_type = 0;
if (ret == RMAP_DENYMATCH)
{
/* Free uninterned attribute. */
bgp_attr_flush (&attr_tmp);
/* Unintern original. */
aspath_unintern (&attr.aspath);
bgp_attr_extra_free (&attr);
bgp_static_withdraw_safi (bgp, p, afi, safi, &bgp_static->prd,
bgp_static->tag);
return;
}
attr_new = bgp_attr_intern (&attr_tmp);
}
else
{
attr_new = bgp_attr_intern (&attr);
}
for (ri = rn->info; ri; ri = ri->next)
if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP
&& ri->sub_type == BGP_ROUTE_STATIC)
break;
if (ri)
{
if (attrhash_cmp (ri->attr, attr_new) &&
!CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
{
bgp_unlock_node (rn);
bgp_attr_unintern (&attr_new);
aspath_unintern (&attr.aspath);
bgp_attr_extra_free (&attr);
return;
}
else
{
/* The attribute is changed. */
bgp_info_set_flag (rn, ri, BGP_INFO_ATTR_CHANGED);
/* Rewrite BGP route information. */
if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED))
bgp_info_restore(rn, ri);
else
bgp_aggregate_decrement (bgp, p, ri, afi, safi);
bgp_attr_unintern (&ri->attr);
ri->attr = attr_new;
ri->uptime = bgp_clock ();
/* Process change. */
bgp_aggregate_increment (bgp, p, ri, afi, safi);
bgp_process (bgp, rn, afi, safi);
bgp_unlock_node (rn);
aspath_unintern (&attr.aspath);
bgp_attr_extra_free (&attr);
return;
}
}
/* Make new BGP info. */
new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self, attr_new,
rn);
SET_FLAG (new->flags, BGP_INFO_VALID);
new->extra = bgp_info_extra_new();
memcpy (new->extra->tag, bgp_static->tag, 3);
/* Aggregate address increment. */
bgp_aggregate_increment (bgp, p, new, afi, safi);
/* Register new BGP information. */
bgp_info_add (rn, new);
/* route_node_get lock */
bgp_unlock_node (rn);
/* Process change. */
bgp_process (bgp, rn, afi, safi);
/* Unintern original. */
aspath_unintern (&attr.aspath);
bgp_attr_extra_free (&attr);
}
/* Configure static BGP network. When user don't run zebra, static
route should be installed as valid. */
static int
@ -3726,10 +3820,7 @@ bgp_static_add (struct bgp *bgp)
for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
{
bgp_static = rn->info;
bgp_static_update_vpnv4 (bgp, &rm->p,
AFI_IP, SAFI_MPLS_VPN,
(struct prefix_rd *)&rn->p,
bgp_static->tag);
bgp_static_update_safi (bgp, &rm->p, bgp_static, afi, safi);
}
}
else
@ -3763,8 +3854,8 @@ bgp_static_delete (struct bgp *bgp)
for (rm = bgp_table_top (table); rm; rm = bgp_route_next (rm))
{
bgp_static = rn->info;
bgp_static_withdraw_vpnv4 (bgp, &rm->p,
AFI_IP, SAFI_MPLS_VPN,
bgp_static_withdraw_safi (bgp, &rm->p,
AFI_IP, safi,
(struct prefix_rd *)&rn->p,
bgp_static->tag);
bgp_static_free (bgp_static);
@ -3846,9 +3937,15 @@ bgp_purge_static_redist_routes (struct bgp *bgp)
bgp_purge_af_static_redist_routes (bgp, afi, safi);
}
/*
* gpz 110624
* Currently this is used to set static routes for VPN and ENCAP.
* I think it can probably be factored with bgp_static_set.
*/
int
bgp_static_set_vpnv4 (struct vty *vty, const char *ip_str, const char *rd_str,
const char *tag_str)
bgp_static_set_safi (safi_t safi, struct vty *vty, const char *ip_str,
const char *rd_str, const char *tag_str,
const char *rmap_str)
{
int ret;
struct prefix p;
@ -3884,10 +3981,10 @@ bgp_static_set_vpnv4 (struct vty *vty, const char *ip_str, const char *rd_str,
return CMD_WARNING;
}
prn = bgp_node_get (bgp->route[AFI_IP][SAFI_MPLS_VPN],
prn = bgp_node_get (bgp->route[AFI_IP][safi],
(struct prefix *)&prd);
if (prn->info == NULL)
prn->info = bgp_table_init (AFI_IP, SAFI_MPLS_VPN);
prn->info = bgp_table_init (AFI_IP, safi);
else
bgp_unlock_node (prn);
table = prn->info;
@ -3903,11 +4000,24 @@ bgp_static_set_vpnv4 (struct vty *vty, const char *ip_str, const char *rd_str,
{
/* New configuration. */
bgp_static = bgp_static_new ();
bgp_static->valid = 1;
memcpy (bgp_static->tag, tag, 3);
bgp_static->backdoor = 0;
bgp_static->valid = 0;
bgp_static->igpmetric = 0;
bgp_static->igpnexthop.s_addr = 0;
memcpy(bgp_static->tag, tag, 3);
bgp_static->prd = prd;
if (rmap_str)
{
if (bgp_static->rmap.name)
free (bgp_static->rmap.name);
bgp_static->rmap.name = strdup (rmap_str);
bgp_static->rmap.map = route_map_lookup_by_name (rmap_str);
}
rn->info = bgp_static;
bgp_static_update_vpnv4 (bgp, &p, AFI_IP, SAFI_MPLS_VPN, &prd, tag);
bgp_static->valid = 1;
bgp_static_update_safi (bgp, &p, bgp_static, AFI_IP, safi);
}
return CMD_SUCCESS;
@ -3915,8 +4025,8 @@ bgp_static_set_vpnv4 (struct vty *vty, const char *ip_str, const char *rd_str,
/* Configure static BGP network. */
int
bgp_static_unset_vpnv4 (struct vty *vty, const char *ip_str,
const char *rd_str, const char *tag_str)
bgp_static_unset_safi(safi_t safi, struct vty *vty, const char *ip_str,
const char *rd_str, const char *tag_str)
{
int ret;
struct bgp *bgp;
@ -3953,10 +4063,10 @@ bgp_static_unset_vpnv4 (struct vty *vty, const char *ip_str,
return CMD_WARNING;
}
prn = bgp_node_get (bgp->route[AFI_IP][SAFI_MPLS_VPN],
prn = bgp_node_get (bgp->route[AFI_IP][safi],
(struct prefix *)&prd);
if (prn->info == NULL)
prn->info = bgp_table_init (AFI_IP, SAFI_MPLS_VPN);
prn->info = bgp_table_init (AFI_IP, safi);
else
bgp_unlock_node (prn);
table = prn->info;
@ -3965,7 +4075,7 @@ bgp_static_unset_vpnv4 (struct vty *vty, const char *ip_str,
if (rn)
{
bgp_static_withdraw_vpnv4 (bgp, &p, AFI_IP, SAFI_MPLS_VPN, &prd, tag);
bgp_static_withdraw_safi (bgp, &p, AFI_IP, safi, &prd, tag);
bgp_static = rn->info;
bgp_static_free (bgp_static);

View File

@ -145,6 +145,9 @@ struct bgp_static
struct route_map *map;
} rmap;
/* Route Distinguisher */
struct prefix_rd prd;
/* MPLS label. */
u_char tag[3];
};
@ -253,10 +256,10 @@ extern void bgp_static_update (struct bgp *, struct prefix *, struct bgp_static
afi_t, safi_t);
extern void bgp_static_withdraw (struct bgp *, struct prefix *, afi_t, safi_t);
extern int bgp_static_set_vpnv4 (struct vty *vty, const char *,
const char *, const char *);
extern int bgp_static_set_safi (safi_t safi, struct vty *vty, const char *,
const char *, const char *, const char *);
extern int bgp_static_unset_vpnv4 (struct vty *, const char *,
extern int bgp_static_unset_safi (safi_t safi, struct vty *, const char *,
const char *, const char *);
/* this is primarily for MPLS-VPN */