mirror of
https://github.com/FRRouting/frr.git
synced 2025-05-01 05:57:15 +02:00
bgpd: vpn-vrf route leaking
- add "debug bgp vpn label" CLI - improved debug messages for "debug bgp bestpath" - send vrf label to zebra after zebra informs bgpd of vrf_id - withdraw vrf_label from zebra if zebra informs bgpd that vrf_id is disabled Signed-off-by: G. Paul Ziemba <paulz@labn.net>
This commit is contained in:
parent
c44bd447cd
commit
ddb5b4880b
139
bgpd/bgp_debug.c
139
bgpd/bgp_debug.c
|
@ -55,6 +55,7 @@ unsigned long conf_bgp_debug_zebra;
|
||||||
unsigned long conf_bgp_debug_allow_martians;
|
unsigned long conf_bgp_debug_allow_martians;
|
||||||
unsigned long conf_bgp_debug_nht;
|
unsigned long conf_bgp_debug_nht;
|
||||||
unsigned long conf_bgp_debug_update_groups;
|
unsigned long conf_bgp_debug_update_groups;
|
||||||
|
unsigned long conf_bgp_debug_vpn;
|
||||||
|
|
||||||
unsigned long term_bgp_debug_as4;
|
unsigned long term_bgp_debug_as4;
|
||||||
unsigned long term_bgp_debug_neighbor_events;
|
unsigned long term_bgp_debug_neighbor_events;
|
||||||
|
@ -68,6 +69,7 @@ unsigned long term_bgp_debug_zebra;
|
||||||
unsigned long term_bgp_debug_allow_martians;
|
unsigned long term_bgp_debug_allow_martians;
|
||||||
unsigned long term_bgp_debug_nht;
|
unsigned long term_bgp_debug_nht;
|
||||||
unsigned long term_bgp_debug_update_groups;
|
unsigned long term_bgp_debug_update_groups;
|
||||||
|
unsigned long term_bgp_debug_vpn;
|
||||||
|
|
||||||
struct list *bgp_debug_neighbor_events_peers = NULL;
|
struct list *bgp_debug_neighbor_events_peers = NULL;
|
||||||
struct list *bgp_debug_keepalive_peers = NULL;
|
struct list *bgp_debug_keepalive_peers = NULL;
|
||||||
|
@ -1557,6 +1559,96 @@ DEFUN (no_debug_bgp_update_groups,
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFUN (debug_bgp_vpn,
|
||||||
|
debug_bgp_vpn_cmd,
|
||||||
|
"debug bgp vpn <leak-from-vrf|leak-to-vrf|rmap-event|label>",
|
||||||
|
DEBUG_STR
|
||||||
|
BGP_STR
|
||||||
|
"VPN routes\n"
|
||||||
|
"leaked from vrf to vpn\n"
|
||||||
|
"leaked to vrf from vpn\n"
|
||||||
|
"route-map updates\n"
|
||||||
|
"labels\n")
|
||||||
|
{
|
||||||
|
int idx = 3;
|
||||||
|
|
||||||
|
if (argv_find(argv, argc, "leak-from-vrf", &idx)) {
|
||||||
|
if (vty->node == CONFIG_NODE)
|
||||||
|
DEBUG_ON(vpn, VPN_LEAK_FROM_VRF);
|
||||||
|
else
|
||||||
|
TERM_DEBUG_ON(vpn, VPN_LEAK_FROM_VRF);
|
||||||
|
} else if (argv_find(argv, argc, "leak-to-vrf", &idx)) {
|
||||||
|
if (vty->node == CONFIG_NODE)
|
||||||
|
DEBUG_ON(vpn, VPN_LEAK_TO_VRF);
|
||||||
|
else
|
||||||
|
TERM_DEBUG_ON(vpn, VPN_LEAK_TO_VRF);
|
||||||
|
} else if (argv_find(argv, argc, "rmap-event", &idx)) {
|
||||||
|
if (vty->node == CONFIG_NODE)
|
||||||
|
DEBUG_ON(vpn, VPN_LEAK_RMAP_EVENT);
|
||||||
|
else
|
||||||
|
TERM_DEBUG_ON(vpn, VPN_LEAK_RMAP_EVENT);
|
||||||
|
} else if (argv_find(argv, argc, "label", &idx)) {
|
||||||
|
if (vty->node == CONFIG_NODE)
|
||||||
|
DEBUG_ON(vpn, VPN_LEAK_LABEL);
|
||||||
|
else
|
||||||
|
TERM_DEBUG_ON(vpn, VPN_LEAK_LABEL);
|
||||||
|
} else {
|
||||||
|
vty_out(vty, "%% unknown debug bgp vpn keyword\n");
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vty->node != CONFIG_NODE)
|
||||||
|
vty_out(vty, "enabled debug bgp vpn %s\n", argv[idx]->text);
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (no_debug_bgp_vpn,
|
||||||
|
no_debug_bgp_vpn_cmd,
|
||||||
|
"no debug bgp vpn <leak-from-vrf|leak-to-vrf|rmap-event|label>",
|
||||||
|
NO_STR
|
||||||
|
DEBUG_STR
|
||||||
|
BGP_STR
|
||||||
|
"VPN routes\n"
|
||||||
|
"leaked from vrf to vpn\n"
|
||||||
|
"leaked to vrf from vpn\n"
|
||||||
|
"route-map updates\n"
|
||||||
|
"labels\n")
|
||||||
|
{
|
||||||
|
int idx = 4;
|
||||||
|
|
||||||
|
if (argv_find(argv, argc, "leak-from-vrf", &idx)) {
|
||||||
|
if (vty->node == CONFIG_NODE)
|
||||||
|
DEBUG_OFF(vpn, VPN_LEAK_FROM_VRF);
|
||||||
|
else
|
||||||
|
TERM_DEBUG_OFF(vpn, VPN_LEAK_FROM_VRF);
|
||||||
|
|
||||||
|
} else if (argv_find(argv, argc, "leak-to-vrf", &idx)) {
|
||||||
|
if (vty->node == CONFIG_NODE)
|
||||||
|
DEBUG_OFF(vpn, VPN_LEAK_TO_VRF);
|
||||||
|
else
|
||||||
|
TERM_DEBUG_OFF(vpn, VPN_LEAK_TO_VRF);
|
||||||
|
} else if (argv_find(argv, argc, "rmap-event", &idx)) {
|
||||||
|
if (vty->node == CONFIG_NODE)
|
||||||
|
DEBUG_OFF(vpn, VPN_LEAK_RMAP_EVENT);
|
||||||
|
else
|
||||||
|
TERM_DEBUG_OFF(vpn, VPN_LEAK_RMAP_EVENT);
|
||||||
|
} else if (argv_find(argv, argc, "label", &idx)) {
|
||||||
|
if (vty->node == CONFIG_NODE)
|
||||||
|
DEBUG_OFF(vpn, VPN_LEAK_LABEL);
|
||||||
|
else
|
||||||
|
TERM_DEBUG_OFF(vpn, VPN_LEAK_LABEL);
|
||||||
|
} else {
|
||||||
|
vty_out(vty, "%% unknown debug bgp vpn keyword\n");
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vty->node != CONFIG_NODE)
|
||||||
|
vty_out(vty, "disabled debug bgp vpn %s\n", argv[idx]->text);
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
DEFUN (no_debug_bgp,
|
DEFUN (no_debug_bgp,
|
||||||
no_debug_bgp_cmd,
|
no_debug_bgp_cmd,
|
||||||
"no debug bgp",
|
"no debug bgp",
|
||||||
|
@ -1589,6 +1681,10 @@ DEFUN (no_debug_bgp,
|
||||||
TERM_DEBUG_OFF(zebra, ZEBRA);
|
TERM_DEBUG_OFF(zebra, ZEBRA);
|
||||||
TERM_DEBUG_OFF(allow_martians, ALLOW_MARTIANS);
|
TERM_DEBUG_OFF(allow_martians, ALLOW_MARTIANS);
|
||||||
TERM_DEBUG_OFF(nht, NHT);
|
TERM_DEBUG_OFF(nht, NHT);
|
||||||
|
TERM_DEBUG_OFF(vpn, VPN_LEAK_FROM_VRF);
|
||||||
|
TERM_DEBUG_OFF(vpn, VPN_LEAK_TO_VRF);
|
||||||
|
TERM_DEBUG_OFF(vpn, VPN_LEAK_RMAP_EVENT);
|
||||||
|
TERM_DEBUG_OFF(vpn, VPN_LEAK_LABEL);
|
||||||
vty_out(vty, "All possible debugging has been turned off\n");
|
vty_out(vty, "All possible debugging has been turned off\n");
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
|
@ -1648,6 +1744,18 @@ DEFUN_NOSH (show_debugging_bgp,
|
||||||
|
|
||||||
if (BGP_DEBUG(allow_martians, ALLOW_MARTIANS))
|
if (BGP_DEBUG(allow_martians, ALLOW_MARTIANS))
|
||||||
vty_out(vty, " BGP allow martian next hop debugging is on\n");
|
vty_out(vty, " BGP allow martian next hop debugging is on\n");
|
||||||
|
|
||||||
|
if (BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF))
|
||||||
|
vty_out(vty,
|
||||||
|
" BGP route leak from vrf to vpn debugging is on\n");
|
||||||
|
if (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF))
|
||||||
|
vty_out(vty,
|
||||||
|
" BGP route leak to vrf from vpn debugging is on\n");
|
||||||
|
if (BGP_DEBUG(vpn, VPN_LEAK_RMAP_EVENT))
|
||||||
|
vty_out(vty, " BGP vpn route-map event debugging is on\n");
|
||||||
|
if (BGP_DEBUG(vpn, VPN_LEAK_LABEL))
|
||||||
|
vty_out(vty, " BGP vpn label event debugging is on\n");
|
||||||
|
|
||||||
vty_out(vty, "\n");
|
vty_out(vty, "\n");
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1692,6 +1800,15 @@ int bgp_debug_count(void)
|
||||||
if (BGP_DEBUG(allow_martians, ALLOW_MARTIANS))
|
if (BGP_DEBUG(allow_martians, ALLOW_MARTIANS))
|
||||||
ret++;
|
ret++;
|
||||||
|
|
||||||
|
if (BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF))
|
||||||
|
ret++;
|
||||||
|
if (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF))
|
||||||
|
ret++;
|
||||||
|
if (BGP_DEBUG(vpn, VPN_LEAK_RMAP_EVENT))
|
||||||
|
ret++;
|
||||||
|
if (BGP_DEBUG(vpn, VPN_LEAK_LABEL))
|
||||||
|
ret++;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1768,6 +1885,23 @@ static int bgp_config_write_debug(struct vty *vty)
|
||||||
write++;
|
write++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CONF_BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF)) {
|
||||||
|
vty_out(vty, "debug bgp vpn leak-from-vrf\n");
|
||||||
|
write++;
|
||||||
|
}
|
||||||
|
if (CONF_BGP_DEBUG(vpn, VPN_LEAK_TO_VRF)) {
|
||||||
|
vty_out(vty, "debug bgp vpn leak-to-vrf\n");
|
||||||
|
write++;
|
||||||
|
}
|
||||||
|
if (CONF_BGP_DEBUG(vpn, VPN_LEAK_RMAP_EVENT)) {
|
||||||
|
vty_out(vty, "debug bgp vpn rmap-event\n");
|
||||||
|
write++;
|
||||||
|
}
|
||||||
|
if (CONF_BGP_DEBUG(vpn, VPN_LEAK_LABEL)) {
|
||||||
|
vty_out(vty, "debug bgp vpn label\n");
|
||||||
|
write++;
|
||||||
|
}
|
||||||
|
|
||||||
return write;
|
return write;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1861,6 +1995,11 @@ void bgp_debug_init(void)
|
||||||
install_element(CONFIG_NODE, &no_debug_bgp_bestpath_cmd);
|
install_element(CONFIG_NODE, &no_debug_bgp_bestpath_cmd);
|
||||||
install_element(ENABLE_NODE, &no_debug_bgp_bestpath_prefix_cmd);
|
install_element(ENABLE_NODE, &no_debug_bgp_bestpath_prefix_cmd);
|
||||||
install_element(CONFIG_NODE, &no_debug_bgp_bestpath_prefix_cmd);
|
install_element(CONFIG_NODE, &no_debug_bgp_bestpath_prefix_cmd);
|
||||||
|
|
||||||
|
install_element(ENABLE_NODE, &debug_bgp_vpn_cmd);
|
||||||
|
install_element(CONFIG_NODE, &debug_bgp_vpn_cmd);
|
||||||
|
install_element(ENABLE_NODE, &no_debug_bgp_vpn_cmd);
|
||||||
|
install_element(CONFIG_NODE, &no_debug_bgp_vpn_cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return true if this prefix is on the per_prefix_list of prefixes to debug
|
/* Return true if this prefix is on the per_prefix_list of prefixes to debug
|
||||||
|
|
|
@ -72,6 +72,7 @@ extern unsigned long conf_bgp_debug_zebra;
|
||||||
extern unsigned long conf_bgp_debug_allow_martians;
|
extern unsigned long conf_bgp_debug_allow_martians;
|
||||||
extern unsigned long conf_bgp_debug_nht;
|
extern unsigned long conf_bgp_debug_nht;
|
||||||
extern unsigned long conf_bgp_debug_update_groups;
|
extern unsigned long conf_bgp_debug_update_groups;
|
||||||
|
extern unsigned long conf_bgp_debug_vpn;
|
||||||
|
|
||||||
extern unsigned long term_bgp_debug_as4;
|
extern unsigned long term_bgp_debug_as4;
|
||||||
extern unsigned long term_bgp_debug_neighbor_events;
|
extern unsigned long term_bgp_debug_neighbor_events;
|
||||||
|
@ -83,6 +84,7 @@ extern unsigned long term_bgp_debug_zebra;
|
||||||
extern unsigned long term_bgp_debug_allow_martians;
|
extern unsigned long term_bgp_debug_allow_martians;
|
||||||
extern unsigned long term_bgp_debug_nht;
|
extern unsigned long term_bgp_debug_nht;
|
||||||
extern unsigned long term_bgp_debug_update_groups;
|
extern unsigned long term_bgp_debug_update_groups;
|
||||||
|
extern unsigned long term_bgp_debug_vpn;
|
||||||
|
|
||||||
extern struct list *bgp_debug_neighbor_events_peers;
|
extern struct list *bgp_debug_neighbor_events_peers;
|
||||||
extern struct list *bgp_debug_keepalive_peers;
|
extern struct list *bgp_debug_keepalive_peers;
|
||||||
|
@ -111,6 +113,10 @@ struct bgp_debug_filter {
|
||||||
#define BGP_DEBUG_ALLOW_MARTIANS 0x01
|
#define BGP_DEBUG_ALLOW_MARTIANS 0x01
|
||||||
#define BGP_DEBUG_NHT 0x01
|
#define BGP_DEBUG_NHT 0x01
|
||||||
#define BGP_DEBUG_UPDATE_GROUPS 0x01
|
#define BGP_DEBUG_UPDATE_GROUPS 0x01
|
||||||
|
#define BGP_DEBUG_VPN_LEAK_FROM_VRF 0x01
|
||||||
|
#define BGP_DEBUG_VPN_LEAK_TO_VRF 0x02
|
||||||
|
#define BGP_DEBUG_VPN_LEAK_RMAP_EVENT 0x04
|
||||||
|
#define BGP_DEBUG_VPN_LEAK_LABEL 0x08
|
||||||
|
|
||||||
#define BGP_DEBUG_PACKET_SEND 0x01
|
#define BGP_DEBUG_PACKET_SEND 0x01
|
||||||
#define BGP_DEBUG_PACKET_SEND_DETAIL 0x02
|
#define BGP_DEBUG_PACKET_SEND_DETAIL 0x02
|
||||||
|
|
|
@ -265,6 +265,8 @@ static int bgp_vrf_enable(struct vrf *vrf)
|
||||||
if (old_vrf_id != bgp->vrf_id)
|
if (old_vrf_id != bgp->vrf_id)
|
||||||
bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
|
bgp_update_redist_vrf_bitmaps(bgp, old_vrf_id);
|
||||||
bgp_instance_up(bgp);
|
bgp_instance_up(bgp);
|
||||||
|
vpn_leak_zebra_vrf_label_update(bgp, AFI_IP);
|
||||||
|
vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -283,6 +285,10 @@ static int bgp_vrf_disable(struct vrf *vrf)
|
||||||
|
|
||||||
bgp = bgp_lookup_by_name(vrf->name);
|
bgp = bgp_lookup_by_name(vrf->name);
|
||||||
if (bgp) {
|
if (bgp) {
|
||||||
|
|
||||||
|
vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP);
|
||||||
|
vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP6);
|
||||||
|
|
||||||
old_vrf_id = bgp->vrf_id;
|
old_vrf_id = bgp->vrf_id;
|
||||||
bgp_handle_socket(bgp, vrf, VRF_UNKNOWN, false);
|
bgp_handle_socket(bgp, vrf, VRF_UNKNOWN, false);
|
||||||
/* We have instance configured, unlink from VRF and make it
|
/* We have instance configured, unlink from VRF and make it
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "bgpd/bgp_route.h"
|
#include "bgpd/bgp_route.h"
|
||||||
#include "bgpd/bgp_rd.h"
|
#include "bgpd/bgp_rd.h"
|
||||||
|
#include "bgpd/bgp_zebra.h"
|
||||||
|
|
||||||
#define MPLS_LABEL_IS_SPECIAL(label) ((label) <= MPLS_LABEL_EXTENSION)
|
#define MPLS_LABEL_IS_SPECIAL(label) ((label) <= MPLS_LABEL_EXTENSION)
|
||||||
#define MPLS_LABEL_IS_NULL(label) \
|
#define MPLS_LABEL_IS_NULL(label) \
|
||||||
|
@ -51,4 +52,122 @@ extern int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd,
|
||||||
enum bgp_show_type type, void *output_arg,
|
enum bgp_show_type type, void *output_arg,
|
||||||
int tags, u_char use_json);
|
int tags, u_char use_json);
|
||||||
|
|
||||||
|
extern void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, struct bgp *bgp_vrf,
|
||||||
|
struct bgp_info *info_vrf);
|
||||||
|
|
||||||
|
extern void vpn_leak_from_vrf_withdraw(struct bgp *bgp_vpn, struct bgp *bgp_vrf,
|
||||||
|
struct bgp_info *info_vrf);
|
||||||
|
|
||||||
|
extern void vpn_leak_from_vrf_withdraw_all(struct bgp *bgp_vpn,
|
||||||
|
struct bgp *bgp_vrf, afi_t afi);
|
||||||
|
|
||||||
|
extern void vpn_leak_from_vrf_update_all(struct bgp *bgp_vpn,
|
||||||
|
struct bgp *bgp_vrf, afi_t afi);
|
||||||
|
|
||||||
|
extern void vpn_leak_to_vrf_withdraw_all(struct bgp *bgp_vrf, afi_t afi);
|
||||||
|
|
||||||
|
extern void vpn_leak_to_vrf_update_all(struct bgp *bgp_vrf, struct bgp *bgp_vpn,
|
||||||
|
afi_t afi);
|
||||||
|
|
||||||
|
extern void vpn_leak_to_vrf_update(struct bgp *bgp_vpn,
|
||||||
|
struct bgp_info *info_vpn);
|
||||||
|
|
||||||
|
extern void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn,
|
||||||
|
struct bgp_info *info_vpn);
|
||||||
|
|
||||||
|
extern void vpn_leak_zebra_vrf_label_update(struct bgp *bgp, afi_t afi);
|
||||||
|
extern void vpn_leak_zebra_vrf_label_withdraw(struct bgp *bgp, afi_t afi);
|
||||||
|
|
||||||
|
static inline int vpn_leak_to_vpn_active(struct bgp *bgp_vrf, afi_t afi,
|
||||||
|
const char **pmsg)
|
||||||
|
{
|
||||||
|
/* Is vrf configured to export to vpn? */
|
||||||
|
if (!CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST],
|
||||||
|
BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) {
|
||||||
|
if (pmsg)
|
||||||
|
*pmsg = "export not set";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is there an RT list set? */
|
||||||
|
if (!bgp_vrf->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN]) {
|
||||||
|
if (pmsg)
|
||||||
|
*pmsg = "rtlist tovpn not defined";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Is there an RD set? */
|
||||||
|
if (!CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
|
||||||
|
BGP_VPN_POLICY_TOVPN_RD_SET)) {
|
||||||
|
if (pmsg)
|
||||||
|
*pmsg = "rd not defined";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int vpn_leak_from_vpn_active(struct bgp *bgp_vrf, afi_t afi,
|
||||||
|
const char **pmsg,
|
||||||
|
struct bgp_redist **pred)
|
||||||
|
{
|
||||||
|
struct bgp_redist *red;
|
||||||
|
|
||||||
|
if (bgp_vrf->inst_type != BGP_INSTANCE_TYPE_VRF
|
||||||
|
&& bgp_vrf->inst_type != BGP_INSTANCE_TYPE_DEFAULT) {
|
||||||
|
|
||||||
|
if (pmsg)
|
||||||
|
*pmsg = "destination bgp instance neither vrf nor default";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hijack zebra redist bits for this route type */
|
||||||
|
red = bgp_redist_lookup(bgp_vrf, afi, ZEBRA_ROUTE_BGP_VPN, 0);
|
||||||
|
if (red) {
|
||||||
|
if (pred)
|
||||||
|
*pred = red;
|
||||||
|
} else {
|
||||||
|
if (pmsg)
|
||||||
|
*pmsg = "redist not set";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (!bgp_vrf->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN]) {
|
||||||
|
if (pmsg)
|
||||||
|
*pmsg = "rtlist fromvpn not defined";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void vpn_leak_prechange(vpn_policy_direction_t direction,
|
||||||
|
afi_t afi, struct bgp *bgp_vpn,
|
||||||
|
struct bgp *bgp_vrf)
|
||||||
|
{
|
||||||
|
if (direction == BGP_VPN_POLICY_DIR_FROMVPN)
|
||||||
|
vpn_leak_to_vrf_withdraw_all(bgp_vrf, afi);
|
||||||
|
if (direction == BGP_VPN_POLICY_DIR_TOVPN)
|
||||||
|
vpn_leak_from_vrf_withdraw_all(bgp_vpn, bgp_vrf, afi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void vpn_leak_postchange(vpn_policy_direction_t direction,
|
||||||
|
afi_t afi, struct bgp *bgp_vpn,
|
||||||
|
struct bgp *bgp_vrf)
|
||||||
|
{
|
||||||
|
if (direction == BGP_VPN_POLICY_DIR_FROMVPN)
|
||||||
|
vpn_leak_to_vrf_update_all(bgp_vrf, bgp_vpn, afi);
|
||||||
|
if (direction == BGP_VPN_POLICY_DIR_TOVPN) {
|
||||||
|
|
||||||
|
if (bgp_vrf->vpn_policy[afi].tovpn_label
|
||||||
|
!= bgp_vrf->vpn_policy[afi]
|
||||||
|
.tovpn_zebra_vrf_label_last_sent) {
|
||||||
|
vpn_leak_zebra_vrf_label_update(bgp_vrf, afi);
|
||||||
|
}
|
||||||
|
|
||||||
|
vpn_leak_from_vrf_update_all(bgp_vpn, bgp_vrf, afi);
|
||||||
|
}
|
||||||
|
if (direction == BGP_VPN_POLICY_DIR_TOVPN)
|
||||||
|
vpn_leak_from_vrf_update_all(bgp_vpn, bgp_vrf, afi);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern void vpn_policy_routemap_event(const char *rmap_name);
|
||||||
|
|
||||||
#endif /* _QUAGGA_BGP_MPLSVPN_H */
|
#endif /* _QUAGGA_BGP_MPLSVPN_H */
|
||||||
|
|
182
bgpd/bgp_route.c
182
bgpd/bgp_route.c
|
@ -1364,6 +1364,16 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (((afi == AFI_IP) || (afi == AFI_IP6))
|
||||||
|
&& ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST))
|
||||||
|
&& (ri->type == ZEBRA_ROUTE_BGP)
|
||||||
|
&& (ri->sub_type == BGP_ROUTE_IMPORTED)) {
|
||||||
|
|
||||||
|
/* Applies to routes leaked vpn->vrf and vrf->vpn */
|
||||||
|
|
||||||
|
samepeer_safe = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* With addpath we may be asked to TX all kinds of paths so make sure
|
/* With addpath we may be asked to TX all kinds of paths so make sure
|
||||||
* ri is valid */
|
* ri is valid */
|
||||||
if (!CHECK_FLAG(ri->flags, BGP_INFO_VALID)
|
if (!CHECK_FLAG(ri->flags, BGP_INFO_VALID)
|
||||||
|
@ -1852,17 +1862,30 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
|
||||||
&& (ri != old_select))
|
&& (ri != old_select))
|
||||||
bgp_info_reap(rn, ri);
|
bgp_info_reap(rn, ri);
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
zlog_debug("%s: ri %p in holddown", __func__,
|
||||||
|
ri);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ri->peer && ri->peer != bgp->peer_self
|
if (ri->peer && ri->peer != bgp->peer_self
|
||||||
&& !CHECK_FLAG(ri->peer->sflags, PEER_STATUS_NSF_WAIT))
|
&& !CHECK_FLAG(ri->peer->sflags, PEER_STATUS_NSF_WAIT))
|
||||||
if (ri->peer->status != Established)
|
if (ri->peer->status != Established) {
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
zlog_debug(
|
||||||
|
"%s: ri %p non self peer %s not estab state",
|
||||||
|
__func__, ri, ri->peer->host);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
|
if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
|
||||||
&& (!CHECK_FLAG(ri->flags, BGP_INFO_DMED_SELECTED))) {
|
&& (!CHECK_FLAG(ri->flags, BGP_INFO_DMED_SELECTED))) {
|
||||||
bgp_info_unset_flag(rn, ri, BGP_INFO_DMED_CHECK);
|
bgp_info_unset_flag(rn, ri, BGP_INFO_DMED_CHECK);
|
||||||
|
if (debug)
|
||||||
|
zlog_debug("%s: ri %p dmed", __func__, ri);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1969,8 +1992,8 @@ int subgroup_process_announce_selected(struct update_subgroup *subgrp,
|
||||||
if (BGP_DEBUG(update, UPDATE_OUT)) {
|
if (BGP_DEBUG(update, UPDATE_OUT)) {
|
||||||
char buf_prefix[PREFIX_STRLEN];
|
char buf_prefix[PREFIX_STRLEN];
|
||||||
prefix2str(p, buf_prefix, sizeof(buf_prefix));
|
prefix2str(p, buf_prefix, sizeof(buf_prefix));
|
||||||
zlog_debug("%s: p=%s, selected=%p",
|
zlog_debug("%s: p=%s, selected=%p", __func__, buf_prefix,
|
||||||
__func__, buf_prefix, selected);
|
selected);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* First update is deferred until ORF or ROUTE-REFRESH is received */
|
/* First update is deferred until ORF or ROUTE-REFRESH is received */
|
||||||
|
@ -2064,6 +2087,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
|
||||||
struct bgp_info *new_select;
|
struct bgp_info *new_select;
|
||||||
struct bgp_info *old_select;
|
struct bgp_info *old_select;
|
||||||
struct bgp_info_pair old_and_new;
|
struct bgp_info_pair old_and_new;
|
||||||
|
char pfx_buf[PREFIX2STR_BUFFER];
|
||||||
|
int debug = 0;
|
||||||
|
|
||||||
/* Is it end of initial update? (after startup) */
|
/* Is it end of initial update? (after startup) */
|
||||||
if (!rn) {
|
if (!rn) {
|
||||||
|
@ -2081,6 +2106,13 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debug = bgp_debug_bestpath(&rn->p);
|
||||||
|
if (debug) {
|
||||||
|
prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
|
||||||
|
zlog_debug("%s: p=%s afi=%s, safi=%s start", __func__, pfx_buf,
|
||||||
|
afi2str(afi), safi2str(safi));
|
||||||
|
}
|
||||||
|
|
||||||
/* Best path selection. */
|
/* Best path selection. */
|
||||||
bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
|
bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
|
||||||
afi, safi);
|
afi, safi);
|
||||||
|
@ -2121,6 +2153,14 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
|
||||||
bgp_unregister_for_label(rn);
|
bgp_unregister_for_label(rn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
|
||||||
|
zlog_debug(
|
||||||
|
"%s: p=%s afi=%s, safi=%s, old_select=%p, new_select=%p",
|
||||||
|
__func__, pfx_buf, afi2str(afi), safi2str(safi),
|
||||||
|
old_select, new_select);
|
||||||
|
}
|
||||||
|
|
||||||
/* If best route remains the same and this is not due to user-initiated
|
/* If best route remains the same and this is not due to user-initiated
|
||||||
* clear, see exactly what needs to be done.
|
* clear, see exactly what needs to be done.
|
||||||
*/
|
*/
|
||||||
|
@ -2135,11 +2175,16 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
|
||||||
vnc_import_bgp_exterior_add_route(bgp, p, old_select);
|
vnc_import_bgp_exterior_add_route(bgp, p, old_select);
|
||||||
#endif
|
#endif
|
||||||
if (bgp_fibupd_safi(safi)
|
if (bgp_fibupd_safi(safi)
|
||||||
&& !bgp_option_check(BGP_OPT_NO_FIB)
|
&& !bgp_option_check(BGP_OPT_NO_FIB)) {
|
||||||
&& new_select->type == ZEBRA_ROUTE_BGP
|
|
||||||
&& new_select->sub_type == BGP_ROUTE_NORMAL)
|
if (new_select->type == ZEBRA_ROUTE_BGP
|
||||||
bgp_zebra_announce(rn, p, old_select, bgp, afi,
|
&& (new_select->sub_type == BGP_ROUTE_NORMAL
|
||||||
safi);
|
|| new_select->sub_type
|
||||||
|
== BGP_ROUTE_IMPORTED))
|
||||||
|
|
||||||
|
bgp_zebra_announce(rn, p, old_select,
|
||||||
|
bgp, afi, safi);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
UNSET_FLAG(old_select->flags, BGP_INFO_MULTIPATH_CHG);
|
UNSET_FLAG(old_select->flags, BGP_INFO_MULTIPATH_CHG);
|
||||||
bgp_zebra_clear_route_change_flags(rn);
|
bgp_zebra_clear_route_change_flags(rn);
|
||||||
|
@ -2186,6 +2231,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
|
||||||
if (old_select)
|
if (old_select)
|
||||||
bgp_info_unset_flag(rn, old_select, BGP_INFO_SELECTED);
|
bgp_info_unset_flag(rn, old_select, BGP_INFO_SELECTED);
|
||||||
if (new_select) {
|
if (new_select) {
|
||||||
|
if (debug)
|
||||||
|
zlog_debug("%s: setting SELECTED flag", __func__);
|
||||||
bgp_info_set_flag(rn, new_select, BGP_INFO_SELECTED);
|
bgp_info_set_flag(rn, new_select, BGP_INFO_SELECTED);
|
||||||
bgp_info_unset_flag(rn, new_select, BGP_INFO_ATTR_CHANGED);
|
bgp_info_unset_flag(rn, new_select, BGP_INFO_ATTR_CHANGED);
|
||||||
UNSET_FLAG(new_select->flags, BGP_INFO_MULTIPATH_CHG);
|
UNSET_FLAG(new_select->flags, BGP_INFO_MULTIPATH_CHG);
|
||||||
|
@ -2221,13 +2268,17 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
|
||||||
&& !bgp_option_check(BGP_OPT_NO_FIB)) {
|
&& !bgp_option_check(BGP_OPT_NO_FIB)) {
|
||||||
if (new_select && new_select->type == ZEBRA_ROUTE_BGP
|
if (new_select && new_select->type == ZEBRA_ROUTE_BGP
|
||||||
&& (new_select->sub_type == BGP_ROUTE_NORMAL
|
&& (new_select->sub_type == BGP_ROUTE_NORMAL
|
||||||
|| new_select->sub_type == BGP_ROUTE_AGGREGATE))
|
|| new_select->sub_type == BGP_ROUTE_AGGREGATE
|
||||||
|
|| new_select->sub_type == BGP_ROUTE_IMPORTED))
|
||||||
|
|
||||||
bgp_zebra_announce(rn, p, new_select, bgp, afi, safi);
|
bgp_zebra_announce(rn, p, new_select, bgp, afi, safi);
|
||||||
else {
|
else {
|
||||||
/* Withdraw the route from the kernel. */
|
/* Withdraw the route from the kernel. */
|
||||||
if (old_select && old_select->type == ZEBRA_ROUTE_BGP
|
if (old_select && old_select->type == ZEBRA_ROUTE_BGP
|
||||||
&& (old_select->sub_type == BGP_ROUTE_NORMAL
|
&& (old_select->sub_type == BGP_ROUTE_NORMAL
|
||||||
|| old_select->sub_type == BGP_ROUTE_AGGREGATE))
|
|| old_select->sub_type == BGP_ROUTE_AGGREGATE
|
||||||
|
|| old_select->sub_type == BGP_ROUTE_IMPORTED))
|
||||||
|
|
||||||
bgp_zebra_withdraw(p, old_select, safi);
|
bgp_zebra_withdraw(p, old_select, safi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3128,6 +3179,18 @@ int bgp_update(struct peer *peer, struct prefix *p, u_int32_t addpath_id,
|
||||||
bgp_process(bgp, rn, afi, safi);
|
bgp_process(bgp, rn, afi, safi);
|
||||||
bgp_unlock_node(rn);
|
bgp_unlock_node(rn);
|
||||||
|
|
||||||
|
if (SAFI_UNICAST == safi
|
||||||
|
&& (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
|
||||||
|
|| bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
|
||||||
|
|
||||||
|
vpn_leak_from_vrf_update(bgp_get_default(), bgp, ri);
|
||||||
|
}
|
||||||
|
if ((SAFI_MPLS_VPN == safi)
|
||||||
|
&& (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
|
||||||
|
|
||||||
|
vpn_leak_to_vrf_update(bgp, ri);
|
||||||
|
}
|
||||||
|
|
||||||
#if ENABLE_BGP_VNC
|
#if ENABLE_BGP_VNC
|
||||||
if (SAFI_MPLS_VPN == safi) {
|
if (SAFI_MPLS_VPN == safi) {
|
||||||
mpls_label_t label_decoded = decode_label(label);
|
mpls_label_t label_decoded = decode_label(label);
|
||||||
|
@ -3244,6 +3307,16 @@ int bgp_update(struct peer *peer, struct prefix *p, u_int32_t addpath_id,
|
||||||
/* Process change. */
|
/* Process change. */
|
||||||
bgp_process(bgp, rn, afi, safi);
|
bgp_process(bgp, rn, afi, safi);
|
||||||
|
|
||||||
|
if (SAFI_UNICAST == safi
|
||||||
|
&& (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
|
||||||
|
|| bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
|
||||||
|
vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
|
||||||
|
}
|
||||||
|
if ((SAFI_MPLS_VPN == safi)
|
||||||
|
&& (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
|
||||||
|
|
||||||
|
vpn_leak_to_vrf_update(bgp, new);
|
||||||
|
}
|
||||||
#if ENABLE_BGP_VNC
|
#if ENABLE_BGP_VNC
|
||||||
if (SAFI_MPLS_VPN == safi) {
|
if (SAFI_MPLS_VPN == safi) {
|
||||||
mpls_label_t label_decoded = decode_label(label);
|
mpls_label_t label_decoded = decode_label(label);
|
||||||
|
@ -3282,6 +3355,18 @@ filtered:
|
||||||
if (safi == SAFI_EVPN)
|
if (safi == SAFI_EVPN)
|
||||||
bgp_evpn_unimport_route(bgp, afi, safi, p, ri);
|
bgp_evpn_unimport_route(bgp, afi, safi, p, ri);
|
||||||
|
|
||||||
|
if (SAFI_UNICAST == safi
|
||||||
|
&& (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
|
||||||
|
|| bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
|
||||||
|
|
||||||
|
vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, ri);
|
||||||
|
}
|
||||||
|
if ((SAFI_MPLS_VPN == safi)
|
||||||
|
&& (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
|
||||||
|
|
||||||
|
vpn_leak_to_vrf_withdraw(bgp, ri);
|
||||||
|
}
|
||||||
|
|
||||||
bgp_rib_remove(rn, ri, peer, afi, safi);
|
bgp_rib_remove(rn, ri, peer, afi, safi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3368,9 +3453,19 @@ int bgp_withdraw(struct peer *peer, struct prefix *p, u_int32_t addpath_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Withdraw specified route from routing table. */
|
/* Withdraw specified route from routing table. */
|
||||||
if (ri && !CHECK_FLAG(ri->flags, BGP_INFO_HISTORY))
|
if (ri && !CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) {
|
||||||
bgp_rib_withdraw(rn, ri, peer, afi, safi, prd);
|
bgp_rib_withdraw(rn, ri, peer, afi, safi, prd);
|
||||||
else if (bgp_debug_update(peer, p, NULL, 1)) {
|
if (SAFI_UNICAST == safi
|
||||||
|
&& (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
|
||||||
|
|| bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
|
||||||
|
vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, ri);
|
||||||
|
}
|
||||||
|
if ((SAFI_MPLS_VPN == safi)
|
||||||
|
&& (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
|
||||||
|
|
||||||
|
vpn_leak_to_vrf_withdraw(bgp, ri);
|
||||||
|
}
|
||||||
|
} else if (bgp_debug_update(peer, p, NULL, 1)) {
|
||||||
bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
|
bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels,
|
||||||
addpath_id ? 1 : 0, addpath_id, pfx_buf,
|
addpath_id ? 1 : 0, addpath_id, pfx_buf,
|
||||||
sizeof(pfx_buf));
|
sizeof(pfx_buf));
|
||||||
|
@ -3854,7 +3949,9 @@ static void bgp_cleanup_table(struct bgp_table *table, safi_t safi)
|
||||||
if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)
|
if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)
|
||||||
&& ri->type == ZEBRA_ROUTE_BGP
|
&& ri->type == ZEBRA_ROUTE_BGP
|
||||||
&& (ri->sub_type == BGP_ROUTE_NORMAL
|
&& (ri->sub_type == BGP_ROUTE_NORMAL
|
||||||
|| ri->sub_type == BGP_ROUTE_AGGREGATE)) {
|
|| ri->sub_type == BGP_ROUTE_AGGREGATE
|
||||||
|
|| ri->sub_type == BGP_ROUTE_IMPORTED)) {
|
||||||
|
|
||||||
if (bgp_fibupd_safi(safi))
|
if (bgp_fibupd_safi(safi))
|
||||||
bgp_zebra_withdraw(&rn->p, ri, safi);
|
bgp_zebra_withdraw(&rn->p, ri, safi);
|
||||||
bgp_info_reap(rn, ri);
|
bgp_info_reap(rn, ri);
|
||||||
|
@ -4255,6 +4352,15 @@ void bgp_static_update(struct bgp *bgp, struct prefix *p,
|
||||||
/* Process change. */
|
/* Process change. */
|
||||||
bgp_aggregate_increment(bgp, p, ri, afi, safi);
|
bgp_aggregate_increment(bgp, p, ri, afi, safi);
|
||||||
bgp_process(bgp, rn, afi, safi);
|
bgp_process(bgp, rn, afi, safi);
|
||||||
|
|
||||||
|
if (SAFI_UNICAST == safi
|
||||||
|
&& (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
|
||||||
|
|| bgp->inst_type
|
||||||
|
== BGP_INSTANCE_TYPE_DEFAULT)) {
|
||||||
|
vpn_leak_from_vrf_update(bgp_get_default(), bgp,
|
||||||
|
ri);
|
||||||
|
}
|
||||||
|
|
||||||
bgp_unlock_node(rn);
|
bgp_unlock_node(rn);
|
||||||
aspath_unintern(&attr.aspath);
|
aspath_unintern(&attr.aspath);
|
||||||
return;
|
return;
|
||||||
|
@ -4302,6 +4408,12 @@ void bgp_static_update(struct bgp *bgp, struct prefix *p,
|
||||||
/* Process change. */
|
/* Process change. */
|
||||||
bgp_process(bgp, rn, afi, safi);
|
bgp_process(bgp, rn, afi, safi);
|
||||||
|
|
||||||
|
if (SAFI_UNICAST == safi
|
||||||
|
&& (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
|
||||||
|
|| bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
|
||||||
|
vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
|
||||||
|
}
|
||||||
|
|
||||||
/* Unintern original. */
|
/* Unintern original. */
|
||||||
aspath_unintern(&attr.aspath);
|
aspath_unintern(&attr.aspath);
|
||||||
}
|
}
|
||||||
|
@ -4322,6 +4434,11 @@ void bgp_static_withdraw(struct bgp *bgp, struct prefix *p, afi_t afi,
|
||||||
|
|
||||||
/* Withdraw static BGP route from routing table. */
|
/* Withdraw static BGP route from routing table. */
|
||||||
if (ri) {
|
if (ri) {
|
||||||
|
if (SAFI_UNICAST == safi
|
||||||
|
&& (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
|
||||||
|
|| bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
|
||||||
|
vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, ri);
|
||||||
|
}
|
||||||
bgp_aggregate_decrement(bgp, p, ri, afi, safi);
|
bgp_aggregate_decrement(bgp, p, ri, afi, safi);
|
||||||
bgp_unlink_nexthop(ri);
|
bgp_unlink_nexthop(ri);
|
||||||
bgp_info_delete(rn, ri);
|
bgp_info_delete(rn, ri);
|
||||||
|
@ -4357,6 +4474,10 @@ static void bgp_static_withdraw_safi(struct bgp *bgp, struct prefix *p,
|
||||||
ri->peer, NULL, p, prd, ri->attr, afi, safi, ri->type,
|
ri->peer, NULL, p, prd, ri->attr, afi, safi, ri->type,
|
||||||
1); /* Kill, since it is an administrative change */
|
1); /* Kill, since it is an administrative change */
|
||||||
#endif
|
#endif
|
||||||
|
if (SAFI_MPLS_VPN == safi
|
||||||
|
&& bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
|
||||||
|
vpn_leak_to_vrf_withdraw(bgp, ri);
|
||||||
|
}
|
||||||
bgp_aggregate_decrement(bgp, p, ri, afi, safi);
|
bgp_aggregate_decrement(bgp, p, ri, afi, safi);
|
||||||
bgp_info_delete(rn, ri);
|
bgp_info_delete(rn, ri);
|
||||||
bgp_process(bgp, rn, afi, safi);
|
bgp_process(bgp, rn, afi, safi);
|
||||||
|
@ -4485,6 +4606,11 @@ static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p,
|
||||||
/* Process change. */
|
/* Process change. */
|
||||||
bgp_aggregate_increment(bgp, p, ri, afi, safi);
|
bgp_aggregate_increment(bgp, p, ri, afi, safi);
|
||||||
bgp_process(bgp, rn, afi, safi);
|
bgp_process(bgp, rn, afi, safi);
|
||||||
|
|
||||||
|
if (SAFI_MPLS_VPN == safi
|
||||||
|
&& bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
|
||||||
|
vpn_leak_to_vrf_update(bgp, ri);
|
||||||
|
}
|
||||||
#if ENABLE_BGP_VNC
|
#if ENABLE_BGP_VNC
|
||||||
rfapiProcessUpdate(ri->peer, NULL, p, &bgp_static->prd,
|
rfapiProcessUpdate(ri->peer, NULL, p, &bgp_static->prd,
|
||||||
ri->attr, afi, safi, ri->type,
|
ri->attr, afi, safi, ri->type,
|
||||||
|
@ -4521,6 +4647,10 @@ static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p,
|
||||||
/* Process change. */
|
/* Process change. */
|
||||||
bgp_process(bgp, rn, afi, safi);
|
bgp_process(bgp, rn, afi, safi);
|
||||||
|
|
||||||
|
if (SAFI_MPLS_VPN == safi
|
||||||
|
&& bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
|
||||||
|
vpn_leak_to_vrf_update(bgp, new);
|
||||||
|
}
|
||||||
#if ENABLE_BGP_VNC
|
#if ENABLE_BGP_VNC
|
||||||
rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
|
rfapiProcessUpdate(new->peer, NULL, p, &bgp_static->prd, new->attr, afi,
|
||||||
safi, new->type, new->sub_type, &label);
|
safi, new->type, new->sub_type, &label);
|
||||||
|
@ -5985,6 +6115,14 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
|
||||||
bgp_process(bgp, bn, afi, SAFI_UNICAST);
|
bgp_process(bgp, bn, afi, SAFI_UNICAST);
|
||||||
bgp_unlock_node(bn);
|
bgp_unlock_node(bn);
|
||||||
aspath_unintern(&attr.aspath);
|
aspath_unintern(&attr.aspath);
|
||||||
|
|
||||||
|
if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
|
||||||
|
|| (bgp->inst_type
|
||||||
|
== BGP_INSTANCE_TYPE_DEFAULT)) {
|
||||||
|
|
||||||
|
vpn_leak_from_vrf_update(
|
||||||
|
bgp_get_default(), bgp, bi);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5997,6 +6135,12 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
|
||||||
bgp_info_add(bn, new);
|
bgp_info_add(bn, new);
|
||||||
bgp_unlock_node(bn);
|
bgp_unlock_node(bn);
|
||||||
bgp_process(bgp, bn, afi, SAFI_UNICAST);
|
bgp_process(bgp, bn, afi, SAFI_UNICAST);
|
||||||
|
|
||||||
|
if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
|
||||||
|
|| (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
|
||||||
|
|
||||||
|
vpn_leak_from_vrf_update(bgp_get_default(), bgp, new);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unintern original. */
|
/* Unintern original. */
|
||||||
|
@ -6023,6 +6167,12 @@ void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, u_char type,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (ri) {
|
if (ri) {
|
||||||
|
if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
|
||||||
|
|| (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
|
||||||
|
|
||||||
|
vpn_leak_from_vrf_withdraw(bgp_get_default(),
|
||||||
|
bgp, ri);
|
||||||
|
}
|
||||||
bgp_aggregate_decrement(bgp, p, ri, afi, SAFI_UNICAST);
|
bgp_aggregate_decrement(bgp, p, ri, afi, SAFI_UNICAST);
|
||||||
bgp_info_delete(rn, ri);
|
bgp_info_delete(rn, ri);
|
||||||
bgp_process(bgp, rn, afi, SAFI_UNICAST);
|
bgp_process(bgp, rn, afi, SAFI_UNICAST);
|
||||||
|
@ -6048,6 +6198,12 @@ void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (ri) {
|
if (ri) {
|
||||||
|
if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
|
||||||
|
|| (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
|
||||||
|
|
||||||
|
vpn_leak_from_vrf_withdraw(bgp_get_default(),
|
||||||
|
bgp, ri);
|
||||||
|
}
|
||||||
bgp_aggregate_decrement(bgp, &rn->p, ri, afi,
|
bgp_aggregate_decrement(bgp, &rn->p, ri, afi,
|
||||||
SAFI_UNICAST);
|
SAFI_UNICAST);
|
||||||
bgp_info_delete(rn, ri);
|
bgp_info_delete(rn, ri);
|
||||||
|
|
|
@ -114,6 +114,30 @@ struct bgp_info_extra {
|
||||||
/* For imported routes into a VNI (or VRF), this points to the parent.
|
/* For imported routes into a VNI (or VRF), this points to the parent.
|
||||||
*/
|
*/
|
||||||
void *parent;
|
void *parent;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some tunnelish parameters follow. Maybe consolidate into an
|
||||||
|
* internal tunnel structure?
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Original bgp instance for imported routes. Needed for:
|
||||||
|
* 1. Find all routes from a specific vrf for deletion
|
||||||
|
* 2. vrf context of original nexthop
|
||||||
|
*
|
||||||
|
* Store pointer to bgp instance rather than bgp->vrf_id because
|
||||||
|
* bgp->vrf_id is not always valid (or may change?).
|
||||||
|
*
|
||||||
|
* Set to NULL if route is not imported from another bgp instance.
|
||||||
|
*/
|
||||||
|
struct bgp *bgp_orig;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Nexthop in context of original bgp instance. Needed
|
||||||
|
* for label resolution of core mpls routes exported to a vrf.
|
||||||
|
* Set nexthop_orig.family to 0 if not valid.
|
||||||
|
*/
|
||||||
|
struct prefix nexthop_orig;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bgp_info {
|
struct bgp_info {
|
||||||
|
@ -179,6 +203,7 @@ struct bgp_info {
|
||||||
#ifdef ENABLE_BGP_VNC
|
#ifdef ENABLE_BGP_VNC
|
||||||
# define BGP_ROUTE_RFP 4
|
# define BGP_ROUTE_RFP 4
|
||||||
#endif
|
#endif
|
||||||
|
#define BGP_ROUTE_IMPORTED 5 /* from another bgp instance/safi */
|
||||||
|
|
||||||
u_short instance;
|
u_short instance;
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
#include "bgpd/bgp_evpn.h"
|
#include "bgpd/bgp_evpn.h"
|
||||||
#include "bgpd/bgp_evpn_private.h"
|
#include "bgpd/bgp_evpn_private.h"
|
||||||
#include "bgpd/bgp_evpn_vty.h"
|
#include "bgpd/bgp_evpn_vty.h"
|
||||||
|
#include "bgpd/bgp_mplsvpn.h"
|
||||||
|
|
||||||
#if ENABLE_BGP_VNC
|
#if ENABLE_BGP_VNC
|
||||||
#include "bgpd/rfapi/bgp_rfapi_cfg.h"
|
#include "bgpd/rfapi/bgp_rfapi_cfg.h"
|
||||||
|
@ -3096,13 +3097,17 @@ static int bgp_route_map_process_update_cb(char *rmap_name)
|
||||||
struct listnode *node, *nnode;
|
struct listnode *node, *nnode;
|
||||||
struct bgp *bgp;
|
struct bgp *bgp;
|
||||||
|
|
||||||
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
|
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
|
||||||
bgp_route_map_process_update(bgp, rmap_name, 1);
|
bgp_route_map_process_update(bgp, rmap_name, 1);
|
||||||
|
|
||||||
#if ENABLE_BGP_VNC
|
#if ENABLE_BGP_VNC
|
||||||
zlog_debug("%s: calling vnc_routemap_update", __func__);
|
/* zlog_debug("%s: calling vnc_routemap_update", __func__); */
|
||||||
vnc_routemap_update(bgp, __func__);
|
vnc_routemap_update(bgp, __func__);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
vpn_policy_routemap_event(rmap_name);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
719
bgpd/bgp_vty.c
719
bgpd/bgp_vty.c
|
@ -6112,6 +6112,526 @@ ALIAS_HIDDEN(no_neighbor_addpath_tx_bestpath_per_as,
|
||||||
NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
|
NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
|
||||||
"Use addpath to advertise the bestpath per each neighboring AS\n")
|
"Use addpath to advertise the bestpath per each neighboring AS\n")
|
||||||
|
|
||||||
|
|
||||||
|
DEFUN_NOSH (vpn_policy_afi,
|
||||||
|
vpn_policy_afi_cmd,
|
||||||
|
"vpn-policy <ipv4|ipv6>",
|
||||||
|
"Enter vpn-policy command mode\n"
|
||||||
|
BGP_AFI_HELP_STR)
|
||||||
|
{
|
||||||
|
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||||
|
if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF
|
||||||
|
&& bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT) {
|
||||||
|
|
||||||
|
vty_out(vty,
|
||||||
|
"vpn-policy supported only in core or vrf instances.\n");
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
afi_t afi;
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
if (argv_find_and_parse_afi(argv, argc, &idx, &afi)) {
|
||||||
|
if (afi == AFI_IP)
|
||||||
|
vty->node = BGP_VPNPOLICY_IPV4_NODE;
|
||||||
|
else
|
||||||
|
vty->node = BGP_VPNPOLICY_IPV6_NODE;
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vpn_policy_afis(struct vty *vty, int *doafi)
|
||||||
|
{
|
||||||
|
switch (vty->node) {
|
||||||
|
case BGP_VPNPOLICY_IPV4_NODE:
|
||||||
|
doafi[AFI_IP] = 1;
|
||||||
|
break;
|
||||||
|
case BGP_VPNPOLICY_IPV6_NODE:
|
||||||
|
doafi[AFI_IP6] = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
vty_out(vty,
|
||||||
|
"%% context error: valid only in vpn-policy block\n");
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
}
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int argv_find_and_parse_vpn_policy_dirs(struct vty *vty,
|
||||||
|
struct cmd_token **argv,
|
||||||
|
int argc, int *idx, int *dodir)
|
||||||
|
{
|
||||||
|
if (argv_find(argv, argc, "fromvpn", idx)) {
|
||||||
|
dodir[BGP_VPN_POLICY_DIR_FROMVPN] = 1;
|
||||||
|
} else if (argv_find(argv, argc, "tovpn", idx)) {
|
||||||
|
dodir[BGP_VPN_POLICY_DIR_TOVPN] = 1;
|
||||||
|
} else if (argv_find(argv, argc, "both", idx)) {
|
||||||
|
dodir[BGP_VPN_POLICY_DIR_FROMVPN] = 1;
|
||||||
|
dodir[BGP_VPN_POLICY_DIR_TOVPN] = 1;
|
||||||
|
} else {
|
||||||
|
vty_out(vty, "%% direction parse error\n");
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
}
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (vpn_policy_rd,
|
||||||
|
vpn_policy_rd_cmd,
|
||||||
|
"rd ASN:NN_OR_IP-ADDRESS:NN",
|
||||||
|
"Specify route distinguisher\n"
|
||||||
|
"Route Distinguisher (<as-number>:<number> | <ip-address>:<number>)\n")
|
||||||
|
{
|
||||||
|
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||||
|
struct prefix_rd prd;
|
||||||
|
int ret;
|
||||||
|
int doafi[AFI_MAX] = {0};
|
||||||
|
afi_t afi;
|
||||||
|
|
||||||
|
ret = str2prefix_rd(argv[1]->arg, &prd);
|
||||||
|
if (!ret) {
|
||||||
|
vty_out(vty, "%% Malformed rd\n");
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = vpn_policy_afis(vty, doafi);
|
||||||
|
if (ret != CMD_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
|
||||||
|
for (afi = 0; afi < AFI_MAX; ++afi) {
|
||||||
|
if (!doafi[afi])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* pre-change: un-export vpn routes (vpn->vrf routes unaffected)
|
||||||
|
*/
|
||||||
|
vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
|
||||||
|
bgp_get_default(), bgp);
|
||||||
|
|
||||||
|
bgp->vpn_policy[afi].tovpn_rd = prd;
|
||||||
|
SET_FLAG(bgp->vpn_policy[afi].flags,
|
||||||
|
BGP_VPN_POLICY_TOVPN_RD_SET);
|
||||||
|
|
||||||
|
/* post-change: re-export vpn routes */
|
||||||
|
vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
|
||||||
|
bgp_get_default(), bgp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (vpn_policy_no_rd,
|
||||||
|
vpn_policy_no_rd_cmd,
|
||||||
|
"no rd",
|
||||||
|
NO_STR
|
||||||
|
"Specify route distinguisher\n")
|
||||||
|
{
|
||||||
|
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||||
|
int ret;
|
||||||
|
int doafi[AFI_MAX] = {0};
|
||||||
|
afi_t afi;
|
||||||
|
|
||||||
|
ret = vpn_policy_afis(vty, doafi);
|
||||||
|
if (ret != CMD_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
|
||||||
|
for (afi = 0; afi < AFI_MAX; ++afi) {
|
||||||
|
if (!doafi[afi])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* pre-change: un-export vpn routes (vpn->vrf routes unaffected)
|
||||||
|
*/
|
||||||
|
vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
|
||||||
|
bgp_get_default(), bgp);
|
||||||
|
|
||||||
|
UNSET_FLAG(bgp->vpn_policy[afi].flags,
|
||||||
|
BGP_VPN_POLICY_TOVPN_RD_SET);
|
||||||
|
|
||||||
|
/* post-change: re-export vpn routes */
|
||||||
|
vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
|
||||||
|
bgp_get_default(), bgp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (vpn_policy_label,
|
||||||
|
vpn_policy_label_cmd,
|
||||||
|
"label (0-1048575)",
|
||||||
|
"label value for VRF\n"
|
||||||
|
"Label Value <0-1048575>\n")
|
||||||
|
{
|
||||||
|
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||||
|
mpls_label_t label;
|
||||||
|
int doafi[AFI_MAX] = {0};
|
||||||
|
afi_t afi;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
label = strtoul(argv[1]->arg, NULL, 10);
|
||||||
|
|
||||||
|
ret = vpn_policy_afis(vty, doafi);
|
||||||
|
if (ret != CMD_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
for (afi = 0; afi < AFI_MAX; ++afi) {
|
||||||
|
if (!doafi[afi])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* pre-change: un-export vpn routes (vpn->vrf routes unaffected)
|
||||||
|
*/
|
||||||
|
vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
|
||||||
|
bgp_get_default(), bgp);
|
||||||
|
|
||||||
|
bgp->vpn_policy[afi].tovpn_label = label;
|
||||||
|
|
||||||
|
/* post-change: re-export vpn routes */
|
||||||
|
vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
|
||||||
|
bgp_get_default(), bgp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (vpn_policy_no_label,
|
||||||
|
vpn_policy_no_label_cmd,
|
||||||
|
"no label",
|
||||||
|
"Negate a command or set its defaults\n"
|
||||||
|
"label value for VRF\n")
|
||||||
|
{
|
||||||
|
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||||
|
int doafi[AFI_MAX] = {0};
|
||||||
|
afi_t afi;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = vpn_policy_afis(vty, doafi);
|
||||||
|
if (ret != CMD_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
for (afi = 0; afi < AFI_MAX; ++afi) {
|
||||||
|
if (!doafi[afi])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* pre-change: un-export vpn routes (vpn->vrf routes unaffected)
|
||||||
|
*/
|
||||||
|
vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
|
||||||
|
bgp_get_default(), bgp);
|
||||||
|
|
||||||
|
bgp->vpn_policy[afi].tovpn_label = MPLS_LABEL_NONE;
|
||||||
|
|
||||||
|
/* post-change: re-export vpn routes */
|
||||||
|
vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
|
||||||
|
bgp_get_default(), bgp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFPY (vpn_policy_nexthop,
|
||||||
|
vpn_policy_nexthop_cmd,
|
||||||
|
"nexthop <A.B.C.D|X:X::X:X>$nexthop",
|
||||||
|
"Specify next hop to use for VRF advertised prefixes\n"
|
||||||
|
"IPv4 prefix\n"
|
||||||
|
"IPv6 prefix\n")
|
||||||
|
{
|
||||||
|
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||||
|
int doafi[AFI_MAX] = {0};
|
||||||
|
afi_t afi;
|
||||||
|
int ret;
|
||||||
|
struct prefix p;
|
||||||
|
|
||||||
|
if (!sockunion2hostprefix(nexthop, &p))
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
|
||||||
|
ret = vpn_policy_afis(vty, doafi);
|
||||||
|
if (ret != CMD_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
for (afi = 0; afi < AFI_MAX; ++afi) {
|
||||||
|
if (!doafi[afi])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pre-change: un-export vpn routes (vpn->vrf routes unaffected)
|
||||||
|
*/
|
||||||
|
vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
|
||||||
|
bgp_get_default(), bgp);
|
||||||
|
|
||||||
|
bgp->vpn_policy[afi].tovpn_nexthop = p;
|
||||||
|
SET_FLAG(bgp->vpn_policy[afi].flags,
|
||||||
|
BGP_VPN_POLICY_TOVPN_NEXTHOP_SET);
|
||||||
|
|
||||||
|
/* post-change: re-export vpn routes */
|
||||||
|
vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
|
||||||
|
bgp_get_default(), bgp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (vpn_policy_no_nexthop,
|
||||||
|
vpn_policy_no_nexthop_cmd,
|
||||||
|
"no nexthop",
|
||||||
|
NO_STR
|
||||||
|
"Specify next hop to use for VRF advertised prefixes\n")
|
||||||
|
{
|
||||||
|
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||||
|
int doafi[AFI_MAX] = {0};
|
||||||
|
afi_t afi;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = vpn_policy_afis(vty, doafi);
|
||||||
|
if (ret != CMD_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
for (afi = 0; afi < AFI_MAX; ++afi) {
|
||||||
|
if (!doafi[afi])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* pre-change: un-export vpn routes (vpn->vrf routes unaffected)
|
||||||
|
*/
|
||||||
|
vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
|
||||||
|
bgp_get_default(), bgp);
|
||||||
|
|
||||||
|
UNSET_FLAG(bgp->vpn_policy[afi].flags,
|
||||||
|
BGP_VPN_POLICY_TOVPN_NEXTHOP_SET);
|
||||||
|
|
||||||
|
/* post-change: re-export vpn routes */
|
||||||
|
vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
|
||||||
|
bgp_get_default(), bgp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_ecom_list(struct vty *vty, int argc, struct cmd_token **argv,
|
||||||
|
struct ecommunity **list)
|
||||||
|
{
|
||||||
|
struct ecommunity *ecom = NULL;
|
||||||
|
struct ecommunity *ecomadd;
|
||||||
|
|
||||||
|
for (; argc; --argc, ++argv) {
|
||||||
|
|
||||||
|
ecomadd = ecommunity_str2com(argv[0]->arg,
|
||||||
|
ECOMMUNITY_ROUTE_TARGET, 0);
|
||||||
|
if (!ecomadd) {
|
||||||
|
vty_out(vty, "Malformed community-list value\n");
|
||||||
|
if (ecom)
|
||||||
|
ecommunity_free(&ecom);
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ecom) {
|
||||||
|
ecommunity_merge(ecom, ecomadd);
|
||||||
|
ecommunity_free(&ecomadd);
|
||||||
|
} else {
|
||||||
|
ecom = ecomadd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*list) {
|
||||||
|
ecommunity_free(&*list);
|
||||||
|
}
|
||||||
|
*list = ecom;
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (vpn_policy_rt,
|
||||||
|
vpn_policy_rt_cmd,
|
||||||
|
"rt <fromvpn|tovpn|both> RTLIST...",
|
||||||
|
"Specify route target list\n"
|
||||||
|
"fromvpn: match any\n"
|
||||||
|
"tovpn: set\n"
|
||||||
|
"both fromvpn: match any and tovpn: set\n"
|
||||||
|
"Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
|
||||||
|
{
|
||||||
|
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||||
|
int ret;
|
||||||
|
struct ecommunity *ecom = NULL;
|
||||||
|
int dodir[BGP_VPN_POLICY_DIR_MAX] = {0};
|
||||||
|
int doafi[AFI_MAX] = {0};
|
||||||
|
vpn_policy_direction_t dir;
|
||||||
|
afi_t afi;
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
ret = vpn_policy_afis(vty, doafi);
|
||||||
|
if (ret != CMD_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = argv_find_and_parse_vpn_policy_dirs(vty, argv, argc, &idx, dodir);
|
||||||
|
if (ret != CMD_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = set_ecom_list(vty, argc - 2, argv + 2, &ecom);
|
||||||
|
if (ret != CMD_SUCCESS) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (afi = 0; afi < AFI_MAX; ++afi) {
|
||||||
|
if (!doafi[afi])
|
||||||
|
continue;
|
||||||
|
for (dir = 0; dir < BGP_VPN_POLICY_DIR_MAX; ++dir) {
|
||||||
|
if (!dodir[dir])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
vpn_leak_prechange(dir, afi, bgp_get_default(), bgp);
|
||||||
|
|
||||||
|
if (bgp->vpn_policy[afi].rtlist[dir])
|
||||||
|
ecommunity_free(
|
||||||
|
&bgp->vpn_policy[afi].rtlist[dir]);
|
||||||
|
bgp->vpn_policy[afi].rtlist[dir] = ecommunity_dup(ecom);
|
||||||
|
|
||||||
|
vpn_leak_postchange(dir, afi, bgp_get_default(), bgp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ecommunity_free(&ecom);
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (vpn_policy_no_rt,
|
||||||
|
vpn_policy_no_rt_cmd,
|
||||||
|
"no rt <fromvpn|tovpn|both>",
|
||||||
|
NO_STR
|
||||||
|
"Specify route target list\n"
|
||||||
|
"fromvpn: match any\n"
|
||||||
|
"tovpn: set\n"
|
||||||
|
"both fromvpn: match any and tovpn: set\n")
|
||||||
|
{
|
||||||
|
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||||
|
int ret;
|
||||||
|
int dodir[BGP_VPN_POLICY_DIR_MAX] = {0};
|
||||||
|
int doafi[AFI_MAX] = {0};
|
||||||
|
vpn_policy_direction_t dir;
|
||||||
|
afi_t afi;
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
ret = vpn_policy_afis(vty, doafi);
|
||||||
|
if (ret != CMD_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = argv_find_and_parse_vpn_policy_dirs(vty, argv, argc, &idx, dodir);
|
||||||
|
if (ret != CMD_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
for (afi = 0; afi < AFI_MAX; ++afi) {
|
||||||
|
if (!doafi[afi])
|
||||||
|
continue;
|
||||||
|
for (dir = 0; dir < BGP_VPN_POLICY_DIR_MAX; ++dir) {
|
||||||
|
if (!dodir[dir])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
vpn_leak_prechange(dir, afi, bgp_get_default(), bgp);
|
||||||
|
|
||||||
|
if (bgp->vpn_policy[afi].rtlist[dir])
|
||||||
|
ecommunity_free(
|
||||||
|
&bgp->vpn_policy[afi].rtlist[dir]);
|
||||||
|
bgp->vpn_policy[afi].rtlist[dir] = NULL;
|
||||||
|
|
||||||
|
vpn_leak_postchange(dir, afi, bgp_get_default(), bgp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (vpn_policy_route_map,
|
||||||
|
vpn_policy_route_map_cmd,
|
||||||
|
"route-map <fromvpn|tovpn> WORD",
|
||||||
|
"Specify route map\n"
|
||||||
|
"fromvpn: core vpn -> this vrf\n"
|
||||||
|
"tovpn: this vrf -> core vpn\n"
|
||||||
|
"name of route-map\n")
|
||||||
|
{
|
||||||
|
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||||
|
int ret;
|
||||||
|
int dodir[BGP_VPN_POLICY_DIR_MAX] = {0};
|
||||||
|
int doafi[AFI_MAX] = {0};
|
||||||
|
vpn_policy_direction_t dir;
|
||||||
|
afi_t afi;
|
||||||
|
int map_name_arg = 2;
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
ret = vpn_policy_afis(vty, doafi);
|
||||||
|
if (ret != CMD_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = argv_find_and_parse_vpn_policy_dirs(vty, argv, argc, &idx, dodir);
|
||||||
|
if (ret != CMD_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
for (afi = 0; afi < AFI_MAX; ++afi) {
|
||||||
|
if (!doafi[afi])
|
||||||
|
continue;
|
||||||
|
for (dir = 0; dir < BGP_VPN_POLICY_DIR_MAX; ++dir) {
|
||||||
|
if (!dodir[dir])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
vpn_leak_prechange(dir, afi, bgp_get_default(), bgp);
|
||||||
|
|
||||||
|
if (bgp->vpn_policy[afi].rmap_name[dir])
|
||||||
|
XFREE(MTYPE_ROUTE_MAP_NAME,
|
||||||
|
bgp->vpn_policy[afi].rmap_name[dir]);
|
||||||
|
bgp->vpn_policy[afi].rmap_name[dir] = XSTRDUP(
|
||||||
|
MTYPE_ROUTE_MAP_NAME, argv[map_name_arg]->arg);
|
||||||
|
bgp->vpn_policy[afi].rmap[dir] =
|
||||||
|
route_map_lookup_by_name(
|
||||||
|
argv[map_name_arg]->arg);
|
||||||
|
|
||||||
|
vpn_leak_postchange(dir, afi, bgp_get_default(), bgp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (vpn_policy_no_route_map,
|
||||||
|
vpn_policy_no_route_map_cmd,
|
||||||
|
"no route-map <fromvpn|tovpn>",
|
||||||
|
NO_STR
|
||||||
|
"Specify route map\n"
|
||||||
|
"fromvpn: core vpn -> this vrf\n"
|
||||||
|
"tovpn: this vrf -> core vpn\n")
|
||||||
|
{
|
||||||
|
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||||
|
int ret;
|
||||||
|
int dodir[BGP_VPN_POLICY_DIR_MAX] = {0};
|
||||||
|
int doafi[AFI_MAX] = {0};
|
||||||
|
vpn_policy_direction_t dir;
|
||||||
|
afi_t afi;
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
ret = vpn_policy_afis(vty, doafi);
|
||||||
|
if (ret != CMD_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = argv_find_and_parse_vpn_policy_dirs(vty, argv, argc, &idx, dodir);
|
||||||
|
if (ret != CMD_SUCCESS)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
for (afi = 0; afi < AFI_MAX; ++afi) {
|
||||||
|
if (!doafi[afi])
|
||||||
|
continue;
|
||||||
|
for (dir = 0; dir < BGP_VPN_POLICY_DIR_MAX; ++dir) {
|
||||||
|
if (!dodir[dir])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
vpn_leak_prechange(dir, afi, bgp_get_default(), bgp);
|
||||||
|
|
||||||
|
if (bgp->vpn_policy[afi].rmap_name[dir])
|
||||||
|
XFREE(MTYPE_ROUTE_MAP_NAME,
|
||||||
|
bgp->vpn_policy[afi].rmap_name[dir]);
|
||||||
|
bgp->vpn_policy[afi].rmap_name[dir] = NULL;
|
||||||
|
bgp->vpn_policy[afi].rmap[dir] = NULL;
|
||||||
|
|
||||||
|
vpn_leak_postchange(dir, afi, bgp_get_default(), bgp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
DEFUN_NOSH (address_family_ipv4_safi,
|
DEFUN_NOSH (address_family_ipv4_safi,
|
||||||
address_family_ipv4_safi_cmd,
|
address_family_ipv4_safi_cmd,
|
||||||
"address-family ipv4 [<unicast|multicast|vpn|labeled-unicast>]",
|
"address-family ipv4 [<unicast|multicast|vpn|labeled-unicast>]",
|
||||||
|
@ -11139,6 +11659,165 @@ void bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This command is valid only in a bgp vrf instance or the default instance */
|
||||||
|
DEFUN (bgp_export_vpn,
|
||||||
|
bgp_export_vpn_cmd,
|
||||||
|
"export vpn",
|
||||||
|
"Export routes to another routing protocol\n"
|
||||||
|
"to VPN RIB per vpn-policy")
|
||||||
|
{
|
||||||
|
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||||
|
int was_off = 0;
|
||||||
|
afi_t afi;
|
||||||
|
safi_t safi;
|
||||||
|
|
||||||
|
if (BGP_INSTANCE_TYPE_VRF != bgp->inst_type
|
||||||
|
&& BGP_INSTANCE_TYPE_DEFAULT != bgp->inst_type) {
|
||||||
|
vty_out(vty,
|
||||||
|
"%% export vpn valid only for bgp vrf or default instance\n");
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
}
|
||||||
|
afi = bgp_node_afi(vty);
|
||||||
|
safi = bgp_node_safi(vty);
|
||||||
|
if ((SAFI_UNICAST != safi) || ((AFI_IP != afi) && (AFI_IP6 != afi))) {
|
||||||
|
vty_out(vty,
|
||||||
|
"%% export vpn valid only for unicast ipv4|ipv6\n");
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||||
|
BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) {
|
||||||
|
was_off = 1;
|
||||||
|
}
|
||||||
|
SET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT);
|
||||||
|
if (was_off) {
|
||||||
|
/* trigger export current vrf */
|
||||||
|
zlog_debug("%s: calling postchange", __func__);
|
||||||
|
vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi,
|
||||||
|
bgp_get_default(), bgp);
|
||||||
|
}
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN (bgp_no_export_vpn,
|
||||||
|
bgp_no_export_vpn_cmd,
|
||||||
|
"no export vpn",
|
||||||
|
NO_STR
|
||||||
|
"Export routes to another routing protocol\n"
|
||||||
|
"to VPN RIB per vpn-policy")
|
||||||
|
{
|
||||||
|
VTY_DECLVAR_CONTEXT(bgp, bgp);
|
||||||
|
int was_on = 0;
|
||||||
|
afi_t afi;
|
||||||
|
safi_t safi;
|
||||||
|
|
||||||
|
if (BGP_INSTANCE_TYPE_VRF != bgp->inst_type
|
||||||
|
&& BGP_INSTANCE_TYPE_DEFAULT != bgp->inst_type) {
|
||||||
|
vty_out(vty,
|
||||||
|
"%% export vpn valid only for bgp vrf or default instance\n");
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
}
|
||||||
|
afi = bgp_node_afi(vty);
|
||||||
|
safi = bgp_node_safi(vty);
|
||||||
|
if ((SAFI_UNICAST != safi) || ((AFI_IP != afi) && (AFI_IP6 != afi))) {
|
||||||
|
vty_out(vty,
|
||||||
|
"%% export vpn valid only for unicast ipv4|ipv6\n");
|
||||||
|
return CMD_WARNING_CONFIG_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||||
|
BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) {
|
||||||
|
was_on = 1;
|
||||||
|
}
|
||||||
|
if (was_on) {
|
||||||
|
/* trigger un-export current vrf */
|
||||||
|
zlog_debug("%s: calling postchange", __func__);
|
||||||
|
vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, afi,
|
||||||
|
bgp_get_default(), bgp);
|
||||||
|
}
|
||||||
|
UNSET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT);
|
||||||
|
return CMD_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,
|
||||||
|
afi_t afi)
|
||||||
|
{
|
||||||
|
vty_frame(vty, " vpn-policy ipv%d\n", ((afi == AFI_IP) ? 4 : 6));
|
||||||
|
|
||||||
|
if (bgp->vpn_policy[afi].tovpn_label != MPLS_LABEL_NONE) {
|
||||||
|
vty_out(vty, " label %u\n",
|
||||||
|
bgp->vpn_policy[afi].tovpn_label);
|
||||||
|
}
|
||||||
|
if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
|
||||||
|
BGP_VPN_POLICY_TOVPN_RD_SET)) {
|
||||||
|
char buf[RD_ADDRSTRLEN];
|
||||||
|
vty_out(vty, " rd %s\n",
|
||||||
|
prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd, buf,
|
||||||
|
sizeof(buf)));
|
||||||
|
}
|
||||||
|
if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
|
||||||
|
BGP_VPN_POLICY_TOVPN_NEXTHOP_SET)) {
|
||||||
|
|
||||||
|
char buf[PREFIX_STRLEN];
|
||||||
|
if (inet_ntop(bgp->vpn_policy[afi].tovpn_nexthop.family,
|
||||||
|
&bgp->vpn_policy[afi].tovpn_nexthop.u.prefix, buf,
|
||||||
|
sizeof(buf))) {
|
||||||
|
|
||||||
|
vty_out(vty, " nexthop %s\n", buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN]
|
||||||
|
&& bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN]
|
||||||
|
&& ecommunity_cmp(
|
||||||
|
bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN],
|
||||||
|
bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN])) {
|
||||||
|
|
||||||
|
char *b = ecommunity_ecom2str(
|
||||||
|
bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN],
|
||||||
|
ECOMMUNITY_FORMAT_ROUTE_MAP, ECOMMUNITY_ROUTE_TARGET);
|
||||||
|
vty_out(vty, " rt both %s\n", b);
|
||||||
|
XFREE(MTYPE_ECOMMUNITY_STR, b);
|
||||||
|
} else {
|
||||||
|
if (bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN]) {
|
||||||
|
char *b = ecommunity_ecom2str(
|
||||||
|
bgp->vpn_policy[afi]
|
||||||
|
.rtlist[BGP_VPN_POLICY_DIR_FROMVPN],
|
||||||
|
ECOMMUNITY_FORMAT_ROUTE_MAP,
|
||||||
|
ECOMMUNITY_ROUTE_TARGET);
|
||||||
|
vty_out(vty, " rt fromvpn %s\n", b);
|
||||||
|
XFREE(MTYPE_ECOMMUNITY_STR, b);
|
||||||
|
}
|
||||||
|
if (bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_TOVPN]) {
|
||||||
|
char *b = ecommunity_ecom2str(
|
||||||
|
bgp->vpn_policy[afi]
|
||||||
|
.rtlist[BGP_VPN_POLICY_DIR_TOVPN],
|
||||||
|
ECOMMUNITY_FORMAT_ROUTE_MAP,
|
||||||
|
ECOMMUNITY_ROUTE_TARGET);
|
||||||
|
vty_out(vty, " rt tovpn %s\n", b);
|
||||||
|
XFREE(MTYPE_ECOMMUNITY_STR, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bgp->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_FROMVPN]) {
|
||||||
|
vty_out(vty, " route-map fromvpn %s\n",
|
||||||
|
bgp->vpn_policy[afi]
|
||||||
|
.rmap_name[BGP_VPN_POLICY_DIR_FROMVPN]);
|
||||||
|
}
|
||||||
|
if (bgp->vpn_policy[afi].rmap_name[BGP_VPN_POLICY_DIR_TOVPN]) {
|
||||||
|
vty_out(vty, " route-map tovpn %s\n",
|
||||||
|
bgp->vpn_policy[afi]
|
||||||
|
.rmap_name[BGP_VPN_POLICY_DIR_TOVPN]);
|
||||||
|
}
|
||||||
|
|
||||||
|
vty_endframe(vty, " exit\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void bgp_vpn_policy_config_write(struct vty *vty, struct bgp *bgp)
|
||||||
|
{
|
||||||
|
bgp_vpn_policy_config_write_afi(vty, bgp, AFI_IP);
|
||||||
|
bgp_vpn_policy_config_write_afi(vty, bgp, AFI_IP6);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* BGP node structure. */
|
/* BGP node structure. */
|
||||||
static struct cmd_node bgp_node = {
|
static struct cmd_node bgp_node = {
|
||||||
BGP_NODE, "%s(config-router)# ", 1,
|
BGP_NODE, "%s(config-router)# ", 1,
|
||||||
|
@ -11180,6 +11859,12 @@ static struct cmd_node bgp_evpn_node = {BGP_EVPN_NODE,
|
||||||
static struct cmd_node bgp_evpn_vni_node = {BGP_EVPN_VNI_NODE,
|
static struct cmd_node bgp_evpn_vni_node = {BGP_EVPN_VNI_NODE,
|
||||||
"%s(config-router-af-vni)# ", 1};
|
"%s(config-router-af-vni)# ", 1};
|
||||||
|
|
||||||
|
static struct cmd_node bgp_vpn_policy_ipv4_node = {
|
||||||
|
BGP_VPNPOLICY_IPV4_NODE, "%s(config-router-vpn-policy-ipv4)# ", 1};
|
||||||
|
|
||||||
|
static struct cmd_node bgp_vpn_policy_ipv6_node = {
|
||||||
|
BGP_VPNPOLICY_IPV6_NODE, "%s(config-router-vpn-policy-ipv6)# ", 1};
|
||||||
|
|
||||||
static void community_list_vty(void);
|
static void community_list_vty(void);
|
||||||
|
|
||||||
static void bgp_ac_neighbor(vector comps, struct cmd_token *token)
|
static void bgp_ac_neighbor(vector comps, struct cmd_token *token)
|
||||||
|
@ -11240,6 +11925,8 @@ void bgp_vty_init(void)
|
||||||
install_node(&bgp_vpnv6_node, NULL);
|
install_node(&bgp_vpnv6_node, NULL);
|
||||||
install_node(&bgp_evpn_node, NULL);
|
install_node(&bgp_evpn_node, NULL);
|
||||||
install_node(&bgp_evpn_vni_node, NULL);
|
install_node(&bgp_evpn_vni_node, NULL);
|
||||||
|
install_node(&bgp_vpn_policy_ipv4_node, NULL);
|
||||||
|
install_node(&bgp_vpn_policy_ipv6_node, NULL);
|
||||||
|
|
||||||
/* Install default VTY commands to new nodes. */
|
/* Install default VTY commands to new nodes. */
|
||||||
install_default(BGP_NODE);
|
install_default(BGP_NODE);
|
||||||
|
@ -11253,6 +11940,8 @@ void bgp_vty_init(void)
|
||||||
install_default(BGP_VPNV6_NODE);
|
install_default(BGP_VPNV6_NODE);
|
||||||
install_default(BGP_EVPN_NODE);
|
install_default(BGP_EVPN_NODE);
|
||||||
install_default(BGP_EVPN_VNI_NODE);
|
install_default(BGP_EVPN_VNI_NODE);
|
||||||
|
install_default(BGP_VPNPOLICY_IPV4_NODE);
|
||||||
|
install_default(BGP_VPNPOLICY_IPV6_NODE);
|
||||||
|
|
||||||
/* "bgp multiple-instance" commands. */
|
/* "bgp multiple-instance" commands. */
|
||||||
install_element(CONFIG_NODE, &bgp_multiple_instance_cmd);
|
install_element(CONFIG_NODE, &bgp_multiple_instance_cmd);
|
||||||
|
@ -12312,6 +13001,12 @@ void bgp_vty_init(void)
|
||||||
install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_rmap_metric_cmd);
|
install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_rmap_metric_cmd);
|
||||||
install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_metric_rmap_cmd);
|
install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_metric_rmap_cmd);
|
||||||
|
|
||||||
|
/* export vpn [route-map WORD] */
|
||||||
|
install_element(BGP_IPV4_NODE, &bgp_export_vpn_cmd);
|
||||||
|
install_element(BGP_IPV6_NODE, &bgp_export_vpn_cmd);
|
||||||
|
install_element(BGP_IPV4_NODE, &bgp_no_export_vpn_cmd);
|
||||||
|
install_element(BGP_IPV6_NODE, &bgp_no_export_vpn_cmd);
|
||||||
|
|
||||||
/* ttl_security commands */
|
/* ttl_security commands */
|
||||||
install_element(BGP_NODE, &neighbor_ttl_security_cmd);
|
install_element(BGP_NODE, &neighbor_ttl_security_cmd);
|
||||||
install_element(BGP_NODE, &no_neighbor_ttl_security_cmd);
|
install_element(BGP_NODE, &no_neighbor_ttl_security_cmd);
|
||||||
|
@ -12330,6 +13025,30 @@ void bgp_vty_init(void)
|
||||||
|
|
||||||
/* Community-list. */
|
/* Community-list. */
|
||||||
community_list_vty();
|
community_list_vty();
|
||||||
|
|
||||||
|
/* vpn-policy commands */
|
||||||
|
install_element(BGP_NODE, &vpn_policy_afi_cmd);
|
||||||
|
install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_rd_cmd);
|
||||||
|
install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_rd_cmd);
|
||||||
|
install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_label_cmd);
|
||||||
|
install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_label_cmd);
|
||||||
|
install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_nexthop_cmd);
|
||||||
|
install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_nexthop_cmd);
|
||||||
|
install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_rt_cmd);
|
||||||
|
install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_rt_cmd);
|
||||||
|
install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_route_map_cmd);
|
||||||
|
install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_route_map_cmd);
|
||||||
|
|
||||||
|
install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_no_rd_cmd);
|
||||||
|
install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_no_rd_cmd);
|
||||||
|
install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_no_label_cmd);
|
||||||
|
install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_no_label_cmd);
|
||||||
|
install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_no_nexthop_cmd);
|
||||||
|
install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_no_nexthop_cmd);
|
||||||
|
install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_no_rt_cmd);
|
||||||
|
install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_no_rt_cmd);
|
||||||
|
install_element(BGP_VPNPOLICY_IPV4_NODE, &vpn_policy_no_route_map_cmd);
|
||||||
|
install_element(BGP_VPNPOLICY_IPV6_NODE, &vpn_policy_no_route_map_cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
|
@ -71,4 +71,5 @@ extern int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty,
|
||||||
safi_t *safi, struct bgp **bgp);
|
safi_t *safi, struct bgp **bgp);
|
||||||
extern int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi,
|
extern int bgp_show_summary_vty(struct vty *vty, const char *name, afi_t afi,
|
||||||
safi_t safi, u_char use_json);
|
safi_t safi, u_char use_json);
|
||||||
|
extern void bgp_vpn_policy_config_write(struct vty *vty, struct bgp *bgp);
|
||||||
#endif /* _QUAGGA_BGP_VTY_H */
|
#endif /* _QUAGGA_BGP_VTY_H */
|
||||||
|
|
141
bgpd/bgp_zebra.c
141
bgpd/bgp_zebra.c
|
@ -54,6 +54,7 @@
|
||||||
#include "bgpd/rfapi/vnc_export_bgp.h"
|
#include "bgpd/rfapi/vnc_export_bgp.h"
|
||||||
#endif
|
#endif
|
||||||
#include "bgpd/bgp_evpn.h"
|
#include "bgpd/bgp_evpn.h"
|
||||||
|
#include "bgpd/bgp_mplsvpn.h"
|
||||||
|
|
||||||
/* All information about zebra. */
|
/* All information about zebra. */
|
||||||
struct zclient *zclient = NULL;
|
struct zclient *zclient = NULL;
|
||||||
|
@ -987,6 +988,7 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||||
struct bgp_info *mpinfo_cp = &local_info;
|
struct bgp_info *mpinfo_cp = &local_info;
|
||||||
route_tag_t tag;
|
route_tag_t tag;
|
||||||
mpls_label_t label;
|
mpls_label_t label;
|
||||||
|
int nh_othervrf = 0;
|
||||||
|
|
||||||
/* Don't try to install if we're not connected to Zebra or Zebra doesn't
|
/* Don't try to install if we're not connected to Zebra or Zebra doesn't
|
||||||
* know of this instance.
|
* know of this instance.
|
||||||
|
@ -997,6 +999,12 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||||
if (bgp->main_zebra_update_hold)
|
if (bgp->main_zebra_update_hold)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vrf leaking support (will have only one nexthop)
|
||||||
|
*/
|
||||||
|
if (info->extra && info->extra->bgp_orig)
|
||||||
|
nh_othervrf = 1;
|
||||||
|
|
||||||
/* Make Zebra API structure. */
|
/* Make Zebra API structure. */
|
||||||
memset(&api, 0, sizeof(api));
|
memset(&api, 0, sizeof(api));
|
||||||
memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr));
|
memcpy(&api.rmac, &(info->attr->rmac), sizeof(struct ethaddr));
|
||||||
|
@ -1008,6 +1016,21 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||||
|
|
||||||
peer = info->peer;
|
peer = info->peer;
|
||||||
|
|
||||||
|
if (info->type == ZEBRA_ROUTE_BGP
|
||||||
|
&& info->sub_type == BGP_ROUTE_IMPORTED) {
|
||||||
|
|
||||||
|
struct bgp_info *bi;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look at parent chain for peer sort
|
||||||
|
*/
|
||||||
|
for (bi = info; bi->extra && bi->extra->parent;
|
||||||
|
bi = bi->extra->parent) {
|
||||||
|
|
||||||
|
peer = ((struct bgp_info *)(bi->extra->parent))->peer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tag = info->attr->tag;
|
tag = info->attr->tag;
|
||||||
|
|
||||||
/* When we create an aggregate route we must also install a Null0 route
|
/* When we create an aggregate route we must also install a Null0 route
|
||||||
|
@ -1060,12 +1083,38 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||||
if (nh_family == AF_INET) {
|
if (nh_family == AF_INET) {
|
||||||
struct in_addr *nexthop;
|
struct in_addr *nexthop;
|
||||||
|
|
||||||
if (bgp->table_map[afi][safi].name) {
|
if (bgp_debug_zebra(&api.prefix)) {
|
||||||
|
char buf_prefix[PREFIX_STRLEN];
|
||||||
|
prefix2str(&api.prefix, buf_prefix,
|
||||||
|
sizeof(buf_prefix));
|
||||||
|
if (mpinfo->extra) {
|
||||||
|
zlog_debug(
|
||||||
|
"%s: p=%s, bgp_is_valid_label: %d",
|
||||||
|
__func__, buf_prefix,
|
||||||
|
bgp_is_valid_label(
|
||||||
|
&mpinfo->extra
|
||||||
|
->label[0]));
|
||||||
|
} else {
|
||||||
|
zlog_debug(
|
||||||
|
"%s: p=%s, extra is NULL, no label",
|
||||||
|
__func__, buf_prefix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bgp->table_map[afi][safi].name || nh_othervrf) {
|
||||||
/* Copy info and attributes, so the route-map
|
/* Copy info and attributes, so the route-map
|
||||||
apply doesn't modify the BGP route info. */
|
apply doesn't modify the BGP route info. */
|
||||||
local_attr = *mpinfo->attr;
|
local_attr = *mpinfo->attr;
|
||||||
mpinfo_cp->attr = &local_attr;
|
mpinfo_cp->attr = &local_attr;
|
||||||
|
if (nh_othervrf) {
|
||||||
|
/* allow route-map to modify */
|
||||||
|
local_attr.nexthop =
|
||||||
|
info->extra->nexthop_orig.u
|
||||||
|
.prefix4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bgp->table_map[afi][safi].name) {
|
||||||
if (!bgp_table_map_apply(
|
if (!bgp_table_map_apply(
|
||||||
bgp->table_map[afi][safi].map, p,
|
bgp->table_map[afi][safi].map, p,
|
||||||
mpinfo_cp))
|
mpinfo_cp))
|
||||||
|
@ -1082,6 +1131,9 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||||
nexthop = &mpinfo_cp->attr->nexthop;
|
nexthop = &mpinfo_cp->attr->nexthop;
|
||||||
|
|
||||||
api_nh->gate.ipv4 = *nexthop;
|
api_nh->gate.ipv4 = *nexthop;
|
||||||
|
api_nh->vrf_id = nh_othervrf
|
||||||
|
? info->extra->bgp_orig->vrf_id
|
||||||
|
: bgp->vrf_id;
|
||||||
/* EVPN type-2 routes are
|
/* EVPN type-2 routes are
|
||||||
programmed as onlink on l3-vni SVI
|
programmed as onlink on l3-vni SVI
|
||||||
*/
|
*/
|
||||||
|
@ -1095,6 +1147,21 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||||
|
|
||||||
ifindex = 0;
|
ifindex = 0;
|
||||||
|
|
||||||
|
if (bgp->table_map[afi][safi].name || nh_othervrf) {
|
||||||
|
/* Copy info and attributes, so the route-map
|
||||||
|
apply doesn't modify the BGP route info. */
|
||||||
|
local_attr = *mpinfo->attr;
|
||||||
|
mpinfo_cp->attr = &local_attr;
|
||||||
|
if (nh_othervrf) {
|
||||||
|
/* allow route-map to modify */
|
||||||
|
local_attr.mp_nexthop_global =
|
||||||
|
info->extra->nexthop_orig.u
|
||||||
|
.prefix6;
|
||||||
|
local_attr.mp_nexthop_len =
|
||||||
|
BGP_ATTR_NHLEN_IPV6_GLOBAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (bgp->table_map[afi][safi].name) {
|
if (bgp->table_map[afi][safi].name) {
|
||||||
/* Copy info and attributes, so the route-map
|
/* Copy info and attributes, so the route-map
|
||||||
apply doesn't modify the BGP route info. */
|
apply doesn't modify the BGP route info. */
|
||||||
|
@ -1139,6 +1206,9 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p,
|
||||||
api_nh->gate.ipv6 = *nexthop;
|
api_nh->gate.ipv6 = *nexthop;
|
||||||
api_nh->ifindex = ifindex;
|
api_nh->ifindex = ifindex;
|
||||||
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX;
|
||||||
|
/* api_nh->vrf_id is not set for normal case? */
|
||||||
|
if (nh_othervrf)
|
||||||
|
api_nh->vrf_id = info->extra->bgp_orig->vrf_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mpinfo->extra
|
if (mpinfo->extra
|
||||||
|
@ -1229,9 +1299,12 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi)
|
||||||
|
|
||||||
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
|
for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn))
|
||||||
for (ri = rn->info; ri; ri = ri->next)
|
for (ri = rn->info; ri; ri = ri->next)
|
||||||
if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)
|
if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED) &&
|
||||||
&& ri->type == ZEBRA_ROUTE_BGP
|
|
||||||
&& ri->sub_type == BGP_ROUTE_NORMAL)
|
(ri->type == ZEBRA_ROUTE_BGP
|
||||||
|
&& (ri->sub_type == BGP_ROUTE_NORMAL
|
||||||
|
|| ri->sub_type == BGP_ROUTE_IMPORTED)))
|
||||||
|
|
||||||
bgp_zebra_announce(rn, &rn->p, ri, bgp, afi,
|
bgp_zebra_announce(rn, &rn->p, ri, bgp, afi,
|
||||||
safi);
|
safi);
|
||||||
}
|
}
|
||||||
|
@ -1244,6 +1317,21 @@ void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, safi_t safi)
|
||||||
peer = info->peer;
|
peer = info->peer;
|
||||||
assert(peer);
|
assert(peer);
|
||||||
|
|
||||||
|
if (info->type == ZEBRA_ROUTE_BGP
|
||||||
|
&& info->sub_type == BGP_ROUTE_IMPORTED) {
|
||||||
|
|
||||||
|
struct bgp_info *bi;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look at parent chain for peer sort
|
||||||
|
*/
|
||||||
|
for (bi = info; bi->extra && bi->extra->parent;
|
||||||
|
bi = bi->extra->parent) {
|
||||||
|
|
||||||
|
peer = ((struct bgp_info *)(bi->extra->parent))->peer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Don't try to install if we're not connected to Zebra or Zebra doesn't
|
/* Don't try to install if we're not connected to Zebra or Zebra doesn't
|
||||||
* know of this instance.
|
* know of this instance.
|
||||||
*/
|
*/
|
||||||
|
@ -1363,7 +1451,27 @@ int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type, u_short instance)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* vpn -> vrf (happens within bgp but we hijack redist bits */
|
||||||
|
if ((bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
|
||||||
|
|| bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
|
||||||
|
&& type == ZEBRA_ROUTE_BGP_VPN) {
|
||||||
|
|
||||||
|
/* leak update all */
|
||||||
|
vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, afi,
|
||||||
|
bgp_get_default(), bgp);
|
||||||
|
}
|
||||||
|
|
||||||
vrf_bitmap_set(zclient->redist[afi][type], bgp->vrf_id);
|
vrf_bitmap_set(zclient->redist[afi][type], bgp->vrf_id);
|
||||||
|
|
||||||
|
/* vpn -> vrf (happens within bgp but we hijack redist bits */
|
||||||
|
if ((bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
|
||||||
|
|| bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
|
||||||
|
&& type == ZEBRA_ROUTE_BGP_VPN) {
|
||||||
|
|
||||||
|
/* leak update all */
|
||||||
|
vpn_leak_postchange(BGP_VPN_POLICY_DIR_FROMVPN, afi,
|
||||||
|
bgp_get_default(), bgp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1484,11 +1592,6 @@ int bgp_redistribute_unreg(struct bgp *bgp, afi_t afi, int type,
|
||||||
vrf_bitmap_unset(zclient->redist[afi][type], bgp->vrf_id);
|
vrf_bitmap_unset(zclient->redist[afi][type], bgp->vrf_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_BGP_VNC
|
|
||||||
if (bgp->vrf_id == VRF_DEFAULT && type == ZEBRA_ROUTE_VNC_DIRECT) {
|
|
||||||
vnc_export_bgp_disable(bgp, afi);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (bgp_install_info_to_zebra(bgp)) {
|
if (bgp_install_info_to_zebra(bgp)) {
|
||||||
/* Send distribute delete message to zebra. */
|
/* Send distribute delete message to zebra. */
|
||||||
|
@ -1512,6 +1615,26 @@ int bgp_redistribute_unset(struct bgp *bgp, afi_t afi, int type,
|
||||||
{
|
{
|
||||||
struct bgp_redist *red;
|
struct bgp_redist *red;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* vnc and vpn->vrf checks must be before red check because
|
||||||
|
* they operate within bgpd irrespective of zebra connection
|
||||||
|
* status. red lookup fails if there is no zebra connection.
|
||||||
|
*/
|
||||||
|
#if ENABLE_BGP_VNC
|
||||||
|
if (bgp->vrf_id == VRF_DEFAULT && type == ZEBRA_ROUTE_VNC_DIRECT) {
|
||||||
|
vnc_export_bgp_disable(bgp, afi);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* vpn -> vrf (happend within bgp but we hijack redist bits */
|
||||||
|
if ((bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
|
||||||
|
|| bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
|
||||||
|
&& type == ZEBRA_ROUTE_BGP_VPN) {
|
||||||
|
|
||||||
|
/* leak withdraw all */
|
||||||
|
vpn_leak_prechange(BGP_VPN_POLICY_DIR_FROMVPN, afi,
|
||||||
|
bgp_get_default(), bgp);
|
||||||
|
}
|
||||||
|
|
||||||
red = bgp_redist_lookup(bgp, afi, type, instance);
|
red = bgp_redist_lookup(bgp, afi, type, instance);
|
||||||
if (!red)
|
if (!red)
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
|
|
13
bgpd/bgpd.c
13
bgpd/bgpd.c
|
@ -2941,6 +2941,11 @@ static struct bgp *bgp_create(as_t *as, const char *name,
|
||||||
}
|
}
|
||||||
#endif /* ENABLE_BGP_VNC */
|
#endif /* ENABLE_BGP_VNC */
|
||||||
|
|
||||||
|
for (afi = AFI_IP; afi < AFI_MAX; afi++) {
|
||||||
|
bgp->vpn_policy[afi].tovpn_label = MPLS_LABEL_NONE;
|
||||||
|
bgp->vpn_policy[afi].tovpn_zebra_vrf_label_last_sent =
|
||||||
|
MPLS_LABEL_NONE;
|
||||||
|
}
|
||||||
if (name) {
|
if (name) {
|
||||||
bgp->name = XSTRDUP(MTYPE_BGP, name);
|
bgp->name = XSTRDUP(MTYPE_BGP, name);
|
||||||
} else {
|
} else {
|
||||||
|
@ -7127,6 +7132,12 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
|
||||||
if (safi == SAFI_EVPN)
|
if (safi == SAFI_EVPN)
|
||||||
bgp_config_write_evpn_info(vty, bgp, afi, safi);
|
bgp_config_write_evpn_info(vty, bgp, afi, safi);
|
||||||
|
|
||||||
|
if (CHECK_FLAG(bgp->af_flags[afi][safi],
|
||||||
|
BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) {
|
||||||
|
|
||||||
|
vty_out(vty, " export vpn\n");
|
||||||
|
}
|
||||||
|
|
||||||
vty_endframe(vty, " exit-address-family\n");
|
vty_endframe(vty, " exit-address-family\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7393,6 +7404,8 @@ int bgp_config_write(struct vty *vty)
|
||||||
if (bgp_option_check(BGP_OPT_CONFIG_CISCO))
|
if (bgp_option_check(BGP_OPT_CONFIG_CISCO))
|
||||||
vty_out(vty, " no auto-summary\n");
|
vty_out(vty, " no auto-summary\n");
|
||||||
|
|
||||||
|
bgp_vpn_policy_config_write(vty, bgp);
|
||||||
|
|
||||||
/* IPv4 unicast configuration. */
|
/* IPv4 unicast configuration. */
|
||||||
bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST);
|
bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST);
|
||||||
|
|
||||||
|
|
23
bgpd/bgpd.h
23
bgpd/bgpd.h
|
@ -159,6 +159,12 @@ struct bgp_redist {
|
||||||
struct bgp_rmap rmap;
|
struct bgp_rmap rmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BGP_VPN_POLICY_DIR_FROMVPN = 0,
|
||||||
|
BGP_VPN_POLICY_DIR_TOVPN = 1,
|
||||||
|
BGP_VPN_POLICY_DIR_MAX = 2
|
||||||
|
} vpn_policy_direction_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Type of 'struct bgp'.
|
* Type of 'struct bgp'.
|
||||||
* - Default: The default instance
|
* - Default: The default instance
|
||||||
|
@ -311,6 +317,7 @@ struct bgp {
|
||||||
/* BGP Per AF flags */
|
/* BGP Per AF flags */
|
||||||
u_int16_t af_flags[AFI_MAX][SAFI_MAX];
|
u_int16_t af_flags[AFI_MAX][SAFI_MAX];
|
||||||
#define BGP_CONFIG_DAMPENING (1 << 0)
|
#define BGP_CONFIG_DAMPENING (1 << 0)
|
||||||
|
#define BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT (1 << 1)
|
||||||
|
|
||||||
/* Route table for next-hop lookup cache. */
|
/* Route table for next-hop lookup cache. */
|
||||||
struct bgp_table *nexthop_cache_table[AFI_MAX];
|
struct bgp_table *nexthop_cache_table[AFI_MAX];
|
||||||
|
@ -448,6 +455,22 @@ struct bgp {
|
||||||
/* route map for advertise ipv4/ipv6 unicast (type-5 routes) */
|
/* route map for advertise ipv4/ipv6 unicast (type-5 routes) */
|
||||||
struct bgp_rmap adv_cmd_rmap[AFI_MAX][SAFI_MAX];
|
struct bgp_rmap adv_cmd_rmap[AFI_MAX][SAFI_MAX];
|
||||||
|
|
||||||
|
/* vpn-policy */
|
||||||
|
struct {
|
||||||
|
struct ecommunity *rtlist[BGP_VPN_POLICY_DIR_MAX];
|
||||||
|
char *rmap_name[BGP_VPN_POLICY_DIR_MAX];
|
||||||
|
struct route_map *rmap[BGP_VPN_POLICY_DIR_MAX];
|
||||||
|
|
||||||
|
/* should be mpls_label_t? */
|
||||||
|
uint32_t tovpn_label; /* may be MPLS_LABEL_NONE */
|
||||||
|
uint32_t tovpn_zebra_vrf_label_last_sent;
|
||||||
|
struct prefix_rd tovpn_rd;
|
||||||
|
struct prefix tovpn_nexthop; /* unset => set to router id */
|
||||||
|
uint32_t flags;
|
||||||
|
#define BGP_VPN_POLICY_TOVPN_RD_SET 0x00000004
|
||||||
|
#define BGP_VPN_POLICY_TOVPN_NEXTHOP_SET 0x00000008
|
||||||
|
} vpn_policy[AFI_MAX];
|
||||||
|
|
||||||
QOBJ_FIELDS
|
QOBJ_FIELDS
|
||||||
};
|
};
|
||||||
DECLARE_QOBJ_TYPE(bgp)
|
DECLARE_QOBJ_TYPE(bgp)
|
||||||
|
|
|
@ -2182,6 +2182,7 @@ void vnc_routemap_update(struct bgp *bgp, const char *unused)
|
||||||
vnc_zlog_debug_verbose("%s done", __func__);
|
vnc_zlog_debug_verbose("%s done", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0 /* superseded */
|
||||||
static void vnc_routemap_event(route_map_event_t type, /* ignored */
|
static void vnc_routemap_event(route_map_event_t type, /* ignored */
|
||||||
const char *rmap_name) /* ignored */
|
const char *rmap_name) /* ignored */
|
||||||
{
|
{
|
||||||
|
@ -2197,6 +2198,7 @@ static void vnc_routemap_event(route_map_event_t type, /* ignored */
|
||||||
|
|
||||||
vnc_zlog_debug_verbose("%s: done", __func__);
|
vnc_zlog_debug_verbose("%s: done", __func__);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
* nve-group
|
* nve-group
|
||||||
|
@ -3673,7 +3675,8 @@ bgp_rfapi_get_ecommunity_by_lni_label(struct bgp *bgp, uint32_t is_import,
|
||||||
void bgp_rfapi_cfg_init(void)
|
void bgp_rfapi_cfg_init(void)
|
||||||
{
|
{
|
||||||
/* main bgpd code does not use this hook, but vnc does */
|
/* main bgpd code does not use this hook, but vnc does */
|
||||||
route_map_event_hook(vnc_routemap_event);
|
/* superseded by bgp_route_map_process_update_cb() */
|
||||||
|
/* bgp_route_map_event_hook_add(vnc_routemap_event); */
|
||||||
|
|
||||||
install_node(&bgp_vnc_defaults_node, NULL);
|
install_node(&bgp_vnc_defaults_node, NULL);
|
||||||
install_node(&bgp_vnc_nve_group_node, NULL);
|
install_node(&bgp_vnc_nve_group_node, NULL);
|
||||||
|
|
Loading…
Reference in a new issue