From 137446f9972eeeec9cb37df485efa471458955a9 Mon Sep 17 00:00:00 2001 From: Lou Berger Date: Tue, 12 Jan 2016 13:41:53 -0500 Subject: [PATCH] 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 Reviewed-by: David Lamparter (cherry picked from commit a76d9ca3584c1751a592457c167c1e146648ceb6) Conflicts: bgpd/bgp_route.c --- bgpd/bgp_mplsvpn.c | 20 ++++- bgpd/bgp_route.c | 210 ++++++++++++++++++++++++++++++++++----------- bgpd/bgp_route.h | 9 +- 3 files changed, 184 insertions(+), 55 deletions(-) diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index d7ac8923e6..3dd2cc51fe 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -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 /, 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); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index adc6407bb9..1b17dc36b5 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -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); diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index cc26249686..8d1eb21010 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -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 */ -- 2.39.5