diff --git a/bgpd/bgp_flowspec_util.c b/bgpd/bgp_flowspec_util.c index c6386dcdb5..cd5bec6267 100644 --- a/bgpd/bgp_flowspec_util.c +++ b/bgpd/bgp_flowspec_util.c @@ -23,6 +23,7 @@ #include "prefix.h" #include "lib_errors.h" +#include "bgp_route.h" #include "bgp_table.h" #include "bgp_flowspec_util.h" #include "bgp_flowspec_private.h" @@ -581,3 +582,27 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len, } return error; } + +/* return 1 if FS entry invalid or no NH IP */ +int bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi, + struct prefix *p) +{ + struct bgp_pbr_entry_main api; + int i; + struct bgp_node *rn = pi->net; + struct bgp_pbr_entry_action *api_action; + + memset(&api, 0, sizeof(struct bgp_pbr_entry_main)); + if (bgp_pbr_build_and_validate_entry(&rn->p, pi, &api) < 0) + return 1; + for (i = 0; i < api.action_num; i++) { + api_action = &api.actions[i]; + if (api_action->action != ACTION_REDIRECT_IP) + continue; + p->family = AF_INET; + p->prefixlen = IPV4_MAX_BITLEN; + p->u.prefix4 = api_action->u.zr.redirect_ip_v4; + return 0; + } + return 1; +} diff --git a/bgpd/bgp_flowspec_util.h b/bgpd/bgp_flowspec_util.h index 9bf05847d3..2ce911da4e 100644 --- a/bgpd/bgp_flowspec_util.h +++ b/bgpd/bgp_flowspec_util.h @@ -54,4 +54,8 @@ extern bool bgp_flowspec_contains_prefix(struct prefix *pfs, struct prefix *input, int prefix_check); +extern int bgp_flowspec_get_first_nh(struct bgp *bgp, + struct bgp_path_info *pi, + struct prefix *nh); + #endif /* _FRR_BGP_FLOWSPEC_UTIL_H */ diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index b6ef5a55c5..2b4ad22b93 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -42,6 +42,7 @@ #include "bgpd/bgp_nht.h" #include "bgpd/bgp_fsm.h" #include "bgpd/bgp_zebra.h" +#include "bgpd/bgp_flowspec_util.h" extern struct zclient *zclient; @@ -533,7 +534,15 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p) && (pi->sub_type == BGP_ROUTE_STATIC)) ? 1 : 0; + struct bgp_node *net = pi->net; + struct prefix *p_orig = &net->p; + if (p_orig->family == AF_FLOWSPEC) { + if (!pi->peer) + return -1; + return bgp_flowspec_get_first_nh(pi->peer->bgp, + pi, p); + } memset(p, 0, sizeof(struct prefix)); switch (afi) { case AFI_IP: diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c index f0a0e615e6..f002154701 100644 --- a/bgpd/bgp_pbr.c +++ b/bgpd/bgp_pbr.c @@ -626,7 +626,7 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api) } /* return -1 if build or validation failed */ -static int bgp_pbr_build_and_validate_entry(struct prefix *p, +int bgp_pbr_build_and_validate_entry(struct prefix *p, struct bgp_path_info *path, struct bgp_pbr_entry_main *api) { diff --git a/bgpd/bgp_pbr.h b/bgpd/bgp_pbr.h index 84095f9ab9..45c3c9ea13 100644 --- a/bgpd/bgp_pbr.h +++ b/bgpd/bgp_pbr.h @@ -290,4 +290,7 @@ extern void bgp_pbr_reset(struct bgp *bgp, afi_t afi); extern struct bgp_pbr_interface *bgp_pbr_interface_lookup(const char *name, struct bgp_pbr_interface_head *head); +extern int bgp_pbr_build_and_validate_entry(struct prefix *p, + struct bgp_path_info *path, + struct bgp_pbr_entry_main *api); #endif /* __BGP_PBR_H__ */