diff options
120 files changed, 2621 insertions, 921 deletions
diff --git a/bgpd/bgp_addpath.c b/bgpd/bgp_addpath.c index aaa77b04dc..75fdb0bb44 100644 --- a/bgpd/bgp_addpath.c +++ b/bgpd/bgp_addpath.c @@ -65,8 +65,8 @@ bgp_addpath_names(enum bgp_addpath_strat strat) /* * Returns if any peer is transmitting addpaths for a given afi/safi. */ -int bgp_addpath_is_addpath_used(struct bgp_addpath_bgp_data *d, afi_t afi, - safi_t safi) +bool bgp_addpath_is_addpath_used(struct bgp_addpath_bgp_data *d, afi_t afi, + safi_t safi) { return d->total_peercount[afi][safi] > 0; } @@ -123,15 +123,15 @@ uint32_t bgp_addpath_id_for_peer(struct peer *peer, afi_t afi, safi_t safi, * Returns true if the path has an assigned addpath ID for any of the addpath * strategies. */ -int bgp_addpath_info_has_ids(struct bgp_addpath_info_data *d) +bool bgp_addpath_info_has_ids(struct bgp_addpath_info_data *d) { int i; for (i = 0; i < BGP_ADDPATH_MAX; i++) if (d->addpath_tx_id[i] != 0) - return 1; + return true; - return 0; + return false; } /* @@ -152,7 +152,7 @@ void bgp_addpath_free_node_data(struct bgp_addpath_bgp_data *bd, /* * Check to see if the addpath strategy requires DMED to be configured to work. */ -int bgp_addpath_dmed_required(int strategy) +bool bgp_addpath_dmed_required(int strategy) { return strategy == BGP_ADDPATH_BEST_PER_AS; } @@ -161,21 +161,20 @@ int bgp_addpath_dmed_required(int strategy) * Return true if this is a path we should advertise due to a * configured addpath-tx knob */ -int bgp_addpath_tx_path(enum bgp_addpath_strat strat, - struct bgp_path_info *pi) +bool bgp_addpath_tx_path(enum bgp_addpath_strat strat, struct bgp_path_info *pi) { switch (strat) { case BGP_ADDPATH_NONE: - return 0; + return false; case BGP_ADDPATH_ALL: - return 1; + return true; case BGP_ADDPATH_BEST_PER_AS: if (CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED)) - return 1; + return true; else - return 0; + return false; default: - return 0; + return false; } } diff --git a/bgpd/bgp_addpath.h b/bgpd/bgp_addpath.h index 786873a004..f61d68e18f 100644 --- a/bgpd/bgp_addpath.h +++ b/bgpd/bgp_addpath.h @@ -32,8 +32,8 @@ void bgp_addpath_init_bgp_data(struct bgp_addpath_bgp_data *d); -int bgp_addpath_is_addpath_used(struct bgp_addpath_bgp_data *d, afi_t afi, - safi_t safi); +bool bgp_addpath_is_addpath_used(struct bgp_addpath_bgp_data *d, afi_t afi, + safi_t safi); void bgp_addpath_free_node_data(struct bgp_addpath_bgp_data *bd, struct bgp_addpath_node_data *nd, @@ -43,7 +43,7 @@ void bgp_addpath_free_info_data(struct bgp_addpath_info_data *d, struct bgp_addpath_node_data *nd); -int bgp_addpath_info_has_ids(struct bgp_addpath_info_data *d); +bool bgp_addpath_info_has_ids(struct bgp_addpath_info_data *d); uint32_t bgp_addpath_id_for_peer(struct peer *peer, afi_t afi, safi_t safi, struct bgp_addpath_info_data *d); @@ -51,14 +51,14 @@ uint32_t bgp_addpath_id_for_peer(struct peer *peer, afi_t afi, safi_t safi, const struct bgp_addpath_strategy_names * bgp_addpath_names(enum bgp_addpath_strat strat); -int bgp_addpath_dmed_required(int strategy); +bool bgp_addpath_dmed_required(int strategy); /* * Return true if this is a path we should advertise due to a configured * addpath-tx knob */ -int bgp_addpath_tx_path(enum bgp_addpath_strat strat, - struct bgp_path_info *pi); +bool bgp_addpath_tx_path(enum bgp_addpath_strat strat, + struct bgp_path_info *pi); /* * Change the type of addpath used for a peer. */ diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c index 8d1c83cf5f..9ee6a24bc5 100644 --- a/bgpd/bgp_advertise.c +++ b/bgpd/bgp_advertise.c @@ -144,8 +144,8 @@ void bgp_advertise_unintern(struct hash *hash, struct bgp_advertise_attr *baa) } } -int bgp_adj_out_lookup(struct peer *peer, struct bgp_node *rn, - uint32_t addpath_tx_id) +bool bgp_adj_out_lookup(struct peer *peer, struct bgp_node *rn, + uint32_t addpath_tx_id) { struct bgp_adj_out *adj; struct peer_af *paf; @@ -169,11 +169,12 @@ int bgp_adj_out_lookup(struct peer *peer, struct bgp_node *rn, && adj->addpath_tx_id != addpath_tx_id) continue; - return (adj->adv ? (adj->adv->baa ? 1 : 0) - : (adj->attr ? 1 : 0)); + return (adj->adv + ? (adj->adv->baa ? true : false) + : (adj->attr ? true : false)); } - return 0; + return false; } @@ -208,8 +209,8 @@ void bgp_adj_in_remove(struct bgp_node *rn, struct bgp_adj_in *bai) XFREE(MTYPE_BGP_ADJ_IN, bai); } -int bgp_adj_in_unset(struct bgp_node *rn, struct peer *peer, - uint32_t addpath_id) +bool bgp_adj_in_unset(struct bgp_node *rn, struct peer *peer, + uint32_t addpath_id) { struct bgp_adj_in *adj; struct bgp_adj_in *adj_next; @@ -217,7 +218,7 @@ int bgp_adj_in_unset(struct bgp_node *rn, struct peer *peer, adj = rn->adj_in; if (!adj) - return 0; + return false; while (adj) { adj_next = adj->next; @@ -230,7 +231,7 @@ int bgp_adj_in_unset(struct bgp_node *rn, struct peer *peer, adj = adj_next; } - return 1; + return true; } void bgp_sync_init(struct peer *peer) diff --git a/bgpd/bgp_advertise.h b/bgpd/bgp_advertise.h index c983598756..6223dc94a3 100644 --- a/bgpd/bgp_advertise.h +++ b/bgpd/bgp_advertise.h @@ -139,10 +139,10 @@ struct bgp_synchronize { #define BGP_ADJ_IN_DEL(N, A) BGP_PATH_INFO_DEL(N, A, adj_in) /* Prototypes. */ -extern int bgp_adj_out_lookup(struct peer *, struct bgp_node *, uint32_t); +extern bool bgp_adj_out_lookup(struct peer *, struct bgp_node *, uint32_t); extern void bgp_adj_in_set(struct bgp_node *, struct peer *, struct attr *, uint32_t); -extern int bgp_adj_in_unset(struct bgp_node *, struct peer *, uint32_t); +extern bool bgp_adj_in_unset(struct bgp_node *, struct peer *, uint32_t); extern void bgp_adj_in_remove(struct bgp_node *, struct bgp_adj_in *); extern void bgp_sync_init(struct peer *); diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index be80675b5d..44962f5af3 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -428,6 +428,22 @@ bool aspath_check_as_sets(struct aspath *aspath) return false; } +/* Check if aspath has BGP_AS_ZERO */ +bool aspath_check_as_zero(struct aspath *aspath) +{ + struct assegment *seg = aspath->segments; + unsigned int i; + + while (seg) { + for (i = 0; i < seg->length; i++) + if (seg->as[i] == BGP_AS_ZERO) + return true; + seg = seg->next; + } + + return false; +} + /* Estimate size aspath /might/ take if encoded into an * ASPATH attribute. * diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h index f327751f33..9df352fcd6 100644 --- a/bgpd/bgp_aspath.h +++ b/bgpd/bgp_aspath.h @@ -39,6 +39,7 @@ #define BGP_PRIVATE_AS4_MAX 4294967294U /* we leave BGP_AS_MAX as the 16bit AS MAX number. */ +#define BGP_AS_ZERO 0 #define BGP_AS_MAX 65535U #define BGP_AS4_MAX 4294967295U /* Transition 16Bit AS as defined by IANA */ @@ -121,6 +122,7 @@ extern bool aspath_left_confed_check(struct aspath *); extern unsigned long aspath_count(void); extern unsigned int aspath_count_hops(const struct aspath *); extern bool aspath_check_as_sets(struct aspath *aspath); +extern bool aspath_check_as_zero(struct aspath *aspath); extern unsigned int aspath_count_confeds(struct aspath *); extern unsigned int aspath_size(struct aspath *); extern as_t aspath_highest(struct aspath *); diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index a1278874c4..0d170e5a30 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -130,14 +130,14 @@ static struct cluster_list *cluster_parse(struct in_addr *pnt, int length) return cluster; } -int cluster_loop_check(struct cluster_list *cluster, struct in_addr originator) +bool cluster_loop_check(struct cluster_list *cluster, struct in_addr originator) { int i; for (i = 0; i < cluster->length / 4; i++) if (cluster->list[i].s_addr == originator.s_addr) - return 1; - return 0; + return true; + return false; } static unsigned int cluster_hash_key_make(const void *p) @@ -263,16 +263,16 @@ void bgp_attr_flush_encap(struct attr *attr) * * This algorithm could be made faster if needed */ -static int encap_same(const struct bgp_attr_encap_subtlv *h1, - const struct bgp_attr_encap_subtlv *h2) +static bool encap_same(const struct bgp_attr_encap_subtlv *h1, + const struct bgp_attr_encap_subtlv *h2) { const struct bgp_attr_encap_subtlv *p; const struct bgp_attr_encap_subtlv *q; if (h1 == h2) - return 1; + return true; if (h1 == NULL || h2 == NULL) - return 0; + return false; for (p = h1; p; p = p->next) { for (q = h2; q; q = q->next) { @@ -283,7 +283,7 @@ static int encap_same(const struct bgp_attr_encap_subtlv *h1, } } if (!q) - return 0; + return false; } for (p = h2; p; p = p->next) { @@ -295,10 +295,10 @@ static int encap_same(const struct bgp_attr_encap_subtlv *h1, } } if (!q) - return 0; + return false; } - return 1; + return true; } static void *encap_hash_alloc(void *p) @@ -1274,7 +1274,7 @@ const uint8_t attr_flags_values[] = { }; static const size_t attr_flags_values_max = array_size(attr_flags_values) - 1; -static int bgp_attr_flag_invalid(struct bgp_attr_parser_args *args) +static bool bgp_attr_flag_invalid(struct bgp_attr_parser_args *args) { uint8_t mask = BGP_ATTR_FLAG_EXTLEN; const uint8_t flags = args->flags; @@ -1282,9 +1282,9 @@ static int bgp_attr_flag_invalid(struct bgp_attr_parser_args *args) /* there may be attributes we don't know about */ if (attr_code > attr_flags_values_max) - return 0; + return false; if (attr_flags_values[attr_code] == 0) - return 0; + return false; /* RFC4271, "For well-known attributes, the Transitive bit MUST be set * to @@ -1296,7 +1296,7 @@ static int bgp_attr_flag_invalid(struct bgp_attr_parser_args *args) EC_BGP_ATTR_FLAG, "%s well-known attributes must have transitive flag set (%x)", lookup_msg(attr_str, attr_code, NULL), flags); - return 1; + return true; } /* "For well-known attributes and for optional non-transitive @@ -1309,7 +1309,7 @@ static int bgp_attr_flag_invalid(struct bgp_attr_parser_args *args) "%s well-known attribute " "must NOT have the partial flag set (%x)", lookup_msg(attr_str, attr_code, NULL), flags); - return 1; + return true; } if (CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL) && !CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS)) { @@ -1317,7 +1317,7 @@ static int bgp_attr_flag_invalid(struct bgp_attr_parser_args *args) "%s optional + transitive attribute " "must NOT have the partial flag set (%x)", lookup_msg(attr_str, attr_code, NULL), flags); - return 1; + return true; } } @@ -1329,10 +1329,10 @@ static int bgp_attr_flag_invalid(struct bgp_attr_parser_args *args) SET_FLAG(mask, BGP_ATTR_FLAG_PARTIAL); if ((flags & ~mask) == attr_flags_values[attr_code]) - return 0; + return false; bgp_attr_flags_diagnose(args, attr_flags_values[attr_code]); - return 1; + return true; } /* Get origin attribute of the update message. */ @@ -1398,6 +1398,15 @@ static int bgp_attr_aspath(struct bgp_attr_parser_args *args) 0); } + /* Codification of AS 0 Processing */ + if (aspath_check_as_zero(attr->aspath)) { + flog_err(EC_BGP_ATTR_MAL_AS_PATH, + "Malformed AS path, contains BGP_AS_ZERO(0) from %s", + peer->host); + return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, + 0); + } + /* Set aspath attribute flag. */ attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH); @@ -1469,6 +1478,15 @@ static int bgp_attr_as4_path(struct bgp_attr_parser_args *args, 0); } + /* Codification of AS 0 Processing */ + if (aspath_check_as_zero(*as4_path)) { + flog_err(EC_BGP_ATTR_MAL_AS_PATH, + "Malformed AS4 path, contains BGP_AS_ZERO(0) from %s", + peer->host); + return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, + 0); + } + /* Set aspath attribute flag. */ attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH); @@ -1615,6 +1633,7 @@ static int bgp_attr_aggregator(struct bgp_attr_parser_args *args) struct peer *const peer = args->peer; struct attr *const attr = args->attr; const bgp_size_t length = args->length; + as_t aggregator_as; int wantedlen = 6; @@ -1632,9 +1651,19 @@ static int bgp_attr_aggregator(struct bgp_attr_parser_args *args) } if (CHECK_FLAG(peer->cap, PEER_CAP_AS4_RCV)) - attr->aggregator_as = stream_getl(peer->curr); + aggregator_as = stream_getl(peer->curr); else - attr->aggregator_as = stream_getw(peer->curr); + aggregator_as = stream_getw(peer->curr); + + /* Codification of AS 0 Processing */ + if (aggregator_as == BGP_AS_ZERO) { + flog_err(EC_BGP_ATTR_LEN, + "AGGREGATOR attribute is BGP_AS_ZERO(0)"); + return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, + args->total); + } + + attr->aggregator_as = aggregator_as; attr->aggregator_addr.s_addr = stream_get_ipv4(peer->curr); /* Set atomic aggregate flag. */ @@ -1652,6 +1681,7 @@ bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args, struct peer *const peer = args->peer; struct attr *const attr = args->attr; const bgp_size_t length = args->length; + as_t aggregator_as; if (length != 8) { flog_err(EC_BGP_ATTR_LEN, "New Aggregator length is not 8 [%d]", @@ -1660,7 +1690,16 @@ bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args, 0); } - *as4_aggregator_as = stream_getl(peer->curr); + /* Codification of AS 0 Processing */ + aggregator_as = stream_getl(peer->curr); + if (aggregator_as == BGP_AS_ZERO) { + flog_err(EC_BGP_ATTR_LEN, + "AS4_AGGREGATOR attribute is BGP_AS_ZERO(0)"); + return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, + 0); + } + + *as4_aggregator_as = aggregator_as; as4_aggregator_addr->s_addr = stream_get_ipv4(peer->curr); attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR); @@ -2343,8 +2382,7 @@ static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */ * Returns 0 if there was an error that needs to be passed up the stack */ static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length, - struct bgp_attr_parser_args *args, - struct bgp_nlri *mp_update) + struct bgp_attr_parser_args *args) { struct peer *const peer = args->peer; struct attr *const attr = args->attr; @@ -2382,15 +2420,6 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length, /* Store label index; subsequently, we'll check on * address-family */ attr->label_index = label_index; - - /* - * Ignore the Label index attribute unless received for - * labeled-unicast - * SAFI. - */ - if (!mp_update->length - || mp_update->safi != SAFI_LABELED_UNICAST) - attr->label_index = BGP_INVALID_LABEL_INDEX; } /* Placeholder code for the IPv6 SID type */ @@ -2589,8 +2618,7 @@ static bgp_attr_parse_ret_t bgp_attr_psid_sub(uint8_t type, uint16_t length, /* Prefix SID attribute * draft-ietf-idr-bgp-prefix-sid-05 */ -bgp_attr_parse_ret_t bgp_attr_prefix_sid(struct bgp_attr_parser_args *args, - struct bgp_nlri *mp_update) +bgp_attr_parse_ret_t bgp_attr_prefix_sid(struct bgp_attr_parser_args *args) { struct peer *const peer = args->peer; struct attr *const attr = args->attr; @@ -2601,8 +2629,10 @@ bgp_attr_parse_ret_t bgp_attr_prefix_sid(struct bgp_attr_parser_args *args, uint8_t type; uint16_t length; size_t headersz = sizeof(type) + sizeof(length); + size_t psid_parsed_length = 0; - while (STREAM_READABLE(peer->curr) > 0) { + while (STREAM_READABLE(peer->curr) > 0 + && psid_parsed_length < args->length) { if (STREAM_READABLE(peer->curr) < headersz) { flog_err( @@ -2620,7 +2650,7 @@ bgp_attr_parse_ret_t bgp_attr_prefix_sid(struct bgp_attr_parser_args *args, if (STREAM_READABLE(peer->curr) < length) { flog_err( EC_BGP_ATTR_LEN, - "Malformed Prefix SID attribute - insufficient data (need %" PRIu8 + "Malformed Prefix SID attribute - insufficient data (need %" PRIu16 " for attribute body, have %zu remaining in UPDATE)", length, STREAM_READABLE(peer->curr)); return bgp_attr_malformed(args, @@ -2628,10 +2658,23 @@ bgp_attr_parse_ret_t bgp_attr_prefix_sid(struct bgp_attr_parser_args *args, args->total); } - ret = bgp_attr_psid_sub(type, length, args, mp_update); + ret = bgp_attr_psid_sub(type, length, args); if (ret != BGP_ATTR_PARSE_PROCEED) return ret; + + psid_parsed_length += length + headersz; + + if (psid_parsed_length > args->length) { + flog_err( + EC_BGP_ATTR_LEN, + "Malformed Prefix SID attribute - TLV overflow by attribute (need %zu" + " for TLV length, have %zu overflowed in UPDATE)", + length + headersz, psid_parsed_length - (length + headersz)); + return bgp_attr_malformed( + args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, + args->total); + } } return BGP_ATTR_PARSE_PROCEED; @@ -3027,7 +3070,7 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr, startp); break; case BGP_ATTR_PREFIX_SID: - ret = bgp_attr_prefix_sid(&attr_args, mp_update); + ret = bgp_attr_prefix_sid(&attr_args); break; case BGP_ATTR_PMSI_TUNNEL: ret = bgp_attr_pmsi_tunnel(&attr_args); @@ -3074,6 +3117,17 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr, } } + /* + * draft-ietf-idr-bgp-prefix-sid-27#section-3: + * About Prefix-SID path attribute, + * Label-Index TLV(type1) and The Originator SRGB TLV(type-3) + * may only appear in a BGP Prefix-SID attribute attached to + * IPv4/IPv6 Labeled Unicast prefixes ([RFC8277]). + * It MUST be ignored when received for other BGP AFI/SAFI combinations. + */ + if (!attr->mp_nexthop_len || mp_update->safi != SAFI_LABELED_UNICAST) + attr->label_index = BGP_INVALID_LABEL_INDEX; + /* Check final read pointer is same as end pointer. */ if (BGP_INPUT_PNT(peer) != endp) { flog_warn(EC_BGP_ATTRIBUTES_MISMATCH, @@ -3508,7 +3562,7 @@ void bgp_packet_mpattr_end(struct stream *s, size_t sizep) stream_putw_at(s, sizep, (stream_get_endp(s) - sizep) - 2); } -static int bgp_append_local_as(struct peer *peer, afi_t afi, safi_t safi) +static bool bgp_append_local_as(struct peer *peer, afi_t afi, safi_t safi) { if (!BGP_AS_IS_PRIVATE(peer->local_as) || (BGP_AS_IS_PRIVATE(peer->local_as) @@ -3520,8 +3574,8 @@ static int bgp_append_local_as(struct peer *peer, afi_t afi, safi_t safi) PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE) && !CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))) - return 1; - return 0; + return true; + return false; } /* Make attribute packet. */ diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 2e91f56df5..f90631c5b9 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -333,7 +333,7 @@ extern unsigned long int attr_count(void); extern unsigned long int attr_unknown_count(void); /* Cluster list prototypes. */ -extern int cluster_loop_check(struct cluster_list *, struct in_addr); +extern bool cluster_loop_check(struct cluster_list *, struct in_addr); extern void cluster_unintern(struct cluster_list *); /* Below exported for unit-test purposes only */ @@ -351,8 +351,7 @@ extern int bgp_mp_reach_parse(struct bgp_attr_parser_args *args, extern int bgp_mp_unreach_parse(struct bgp_attr_parser_args *args, struct bgp_nlri *); extern bgp_attr_parse_ret_t -bgp_attr_prefix_sid(struct bgp_attr_parser_args *args, - struct bgp_nlri *mp_update); +bgp_attr_prefix_sid(struct bgp_attr_parser_args *args); extern struct bgp_attr_encap_subtlv * encap_tlv_dup(struct bgp_attr_encap_subtlv *orig); diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c index ec9656a98d..6941e1f9b5 100644 --- a/bgpd/bgp_attr_evpn.c +++ b/bgpd/bgp_attr_evpn.c @@ -54,25 +54,25 @@ void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac) * format accepted: AA:BB:CC:DD:EE:FF:GG:HH:II:JJ * if id is null, check only is done */ -int str2esi(const char *str, struct eth_segment_id *id) +bool str2esi(const char *str, struct eth_segment_id *id) { unsigned int a[ESI_LEN]; int i; if (!str) - return 0; + return false; if (sscanf(str, "%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x", a + 0, a + 1, a + 2, a + 3, a + 4, a + 5, a + 6, a + 7, a + 8, a + 9) != ESI_LEN) { /* error in incoming str length */ - return 0; + return false; } /* valid mac address */ if (!id) - return 1; + return true; for (i = 0; i < ESI_LEN; ++i) id->val[i] = a[i] & 0xff; - return 1; + return true; } char *esi2str(struct eth_segment_id *id) diff --git a/bgpd/bgp_attr_evpn.h b/bgpd/bgp_attr_evpn.h index 25654ba709..c1bfd83765 100644 --- a/bgpd/bgp_attr_evpn.h +++ b/bgpd/bgp_attr_evpn.h @@ -51,7 +51,7 @@ struct bgp_route_evpn { union gw_addr gw_ip; }; -extern int str2esi(const char *str, struct eth_segment_id *id); +extern bool str2esi(const char *str, struct eth_segment_id *id); extern char *esi2str(struct eth_segment_id *id); extern char *ecom_mac2str(char *ecom_mac); diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index 1f650aaeb7..a200589bd3 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -72,21 +72,21 @@ void bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer) * bgp_bfd_is_peer_multihop - returns whether BFD peer is multi-hop or single * hop. */ -int bgp_bfd_is_peer_multihop(struct peer *peer) +bool bgp_bfd_is_peer_multihop(struct peer *peer) { struct bfd_info *bfd_info; bfd_info = (struct bfd_info *)peer->bfd_info; if (!bfd_info) - return 0; + return false; if ((bfd_info->type == BFD_TYPE_MULTIHOP) || ((peer->sort == BGP_PEER_IBGP) && !peer->shared_network) || is_ebgp_multihop_configured(peer)) - return 1; + return true; else - return 0; + return false; } /* @@ -200,6 +200,25 @@ static void bgp_bfd_update_peer(struct peer *peer) bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_UPDATE); } +/** + * bgp_bfd_reset_peer - reinitialise bfd + * ensures that bfd state machine is restarted + * to be synced with remote bfd + */ +void bgp_bfd_reset_peer(struct peer *peer) +{ + struct bfd_info *bfd_info; + + if (!peer->bfd_info) + return; + bfd_info = (struct bfd_info *)peer->bfd_info; + + /* if status is not down, reset bfd */ + if (bfd_info->status != BFD_STATUS_DOWN) + bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER); + bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER); +} + /* * bgp_bfd_update_type - update session type with BFD through zebra. */ diff --git a/bgpd/bgp_bfd.h b/bgpd/bgp_bfd.h index caa5651e3a..f2fa959b45 100644 --- a/bgpd/bgp_bfd.h +++ b/bgpd/bgp_bfd.h @@ -31,12 +31,14 @@ extern void bgp_bfd_register_peer(struct peer *peer); extern void bgp_bfd_deregister_peer(struct peer *peer); +extern void bgp_bfd_reset_peer(struct peer *peer); + extern void bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr); extern void bgp_bfd_show_info(struct vty *vty, struct peer *peer, bool use_json, json_object *json_neigh); -extern int bgp_bfd_is_peer_multihop(struct peer *peer); +extern bool bgp_bfd_is_peer_multihop(struct peer *peer); #endif /* _QUAGGA_BGP_BFD_H */ diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c index 24a9cab5d1..32865da376 100644 --- a/bgpd/bgp_bmp.c +++ b/bgpd/bgp_bmp.c @@ -664,8 +664,7 @@ static int bmp_peer_established(struct peer *peer) return 0; /* Check if this peer just went to Established */ - if ((peer->last_major_event != OpenConfirm) || - !(peer_established(peer))) + if ((peer->ostatus != OpenConfirm) || !(peer_established(peer))) return 0; if (peer->doppelganger && (peer->doppelganger->status != Deleted)) { diff --git a/bgpd/bgp_btoa.c b/bgpd/bgp_btoa.c index cc37e352ef..cbe18e23cb 100644 --- a/bgpd/bgp_btoa.c +++ b/bgpd/bgp_btoa.c @@ -68,7 +68,7 @@ enum MRT_MSG_TYPES { MSG_TABLE_DUMP /* routing table dump */ }; -static int attr_parse(struct stream *s, uint16_t len) +static void attr_parse(struct stream *s, uint16_t len) { unsigned int flag; unsigned int type; @@ -115,8 +115,6 @@ static int attr_parse(struct stream *s, uint16_t len) break; } } - - return 0; } int main(int argc, char **argv) diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c index c145c47d02..195c0f394c 100644 --- a/bgpd/bgp_community.c +++ b/bgpd/bgp_community.c @@ -128,7 +128,7 @@ static int community_compare(const void *a1, const void *a2) return 0; } -int community_include(struct community *com, uint32_t val) +bool community_include(struct community *com, uint32_t val) { int i; @@ -136,9 +136,8 @@ int community_include(struct community *com, uint32_t val) for (i = 0; i < com->size; i++) if (memcmp(&val, com_nthval(com, i), sizeof(uint32_t)) == 0) - return 1; - - return 0; + return true; + return false; } uint32_t community_val_get(struct community *com, int i) @@ -564,19 +563,19 @@ unsigned int community_hash_make(const struct community *com) return jhash2(pnt, com->size, 0x43ea96c1); } -int community_match(const struct community *com1, const struct community *com2) +bool community_match(const struct community *com1, const struct community *com2) { int i = 0; int j = 0; if (com1 == NULL && com2 == NULL) - return 1; + return true; if (com1 == NULL || com2 == NULL) - return 0; + return false; if (com1->size < com2->size) - return 0; + return false; /* Every community on com2 needs to be on com1 for this to match */ while (i < com1->size && j < com2->size) { @@ -586,9 +585,9 @@ int community_match(const struct community *com1, const struct community *com2) } if (j == com2->size) - return 1; + return true; else - return 0; + return false; } /* If two aspath have same value then return 1 else return 0. This diff --git a/bgpd/bgp_community.h b/bgpd/bgp_community.h index 74a3a6b507..31a061370d 100644 --- a/bgpd/bgp_community.h +++ b/bgpd/bgp_community.h @@ -77,7 +77,7 @@ extern void community_unintern(struct community **); extern char *community_str(struct community *, bool make_json); extern unsigned int community_hash_make(const struct community *); extern struct community *community_str2com(const char *); -extern int community_match(const struct community *, const struct community *); +extern bool community_match(const struct community *, const struct community *); extern bool community_cmp(const struct community *c1, const struct community *c2); extern struct community *community_merge(struct community *, @@ -85,7 +85,7 @@ extern struct community *community_merge(struct community *, extern struct community *community_delete(struct community *, struct community *); extern struct community *community_dup(struct community *); -extern int community_include(struct community *, uint32_t); +extern bool community_include(struct community *, uint32_t); extern void community_del_val(struct community *, uint32_t *); extern unsigned long community_count(void); extern struct hash *community_hash(void); diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index 2e21c7222c..b552b8811c 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -184,8 +184,8 @@ static const struct message bgp_notify_fsm_msg[] = { const char *const bgp_origin_str[] = {"i", "e", "?"}; const char *const bgp_origin_long_str[] = {"IGP", "EGP", "incomplete"}; -static int bgp_debug_print_evpn_prefix(struct vty *vty, const char *desc, - struct prefix *p); +static void bgp_debug_print_evpn_prefix(struct vty *vty, const char *desc, + struct prefix *p); /* Given a string return a pointer the corresponding peer structure */ static struct peer *bgp_find_peer(struct vty *vty, const char *peer_str) { @@ -315,8 +315,8 @@ static void bgp_debug_list_add_entry(struct list *list, const char *host, listnode_add(list, filter); } -static int bgp_debug_list_remove_entry(struct list *list, const char *host, - struct prefix *p) +static bool bgp_debug_list_remove_entry(struct list *list, const char *host, + struct prefix *p) { struct bgp_debug_filter *filter; struct listnode *node, *nnode; @@ -326,21 +326,21 @@ static int bgp_debug_list_remove_entry(struct list *list, const char *host, listnode_delete(list, filter); XFREE(MTYPE_BGP_DEBUG_STR, filter->host); XFREE(MTYPE_BGP_DEBUG_FILTER, filter); - return 1; + return true; } else if (p && filter->p->prefixlen == p->prefixlen && prefix_match(filter->p, p)) { listnode_delete(list, filter); prefix_free(&filter->p); XFREE(MTYPE_BGP_DEBUG_FILTER, filter); - return 1; + return true; } } - return 0; + return false; } -static int bgp_debug_list_has_entry(struct list *list, const char *host, - const struct prefix *p) +static bool bgp_debug_list_has_entry(struct list *list, const char *host, + const struct prefix *p) { struct bgp_debug_filter *filter; struct listnode *node, *nnode; @@ -348,32 +348,32 @@ static int bgp_debug_list_has_entry(struct list *list, const char *host, for (ALL_LIST_ELEMENTS(list, node, nnode, filter)) { if (host) { if (strcmp(filter->host, host) == 0) { - return 1; + return true; } } else if (p) { if (filter->p->prefixlen == p->prefixlen && prefix_match(filter->p, p)) { - return 1; + return true; } } } - return 0; + return false; } -int bgp_debug_peer_updout_enabled(char *host) +bool bgp_debug_peer_updout_enabled(char *host) { return (bgp_debug_list_has_entry(bgp_debug_update_out_peers, host, NULL)); } /* Dump attribute. */ -int bgp_dump_attr(struct attr *attr, char *buf, size_t size) +bool bgp_dump_attr(struct attr *attr, char *buf, size_t size) { char addrbuf[BUFSIZ]; if (!attr) - return 0; + return false; buf[0] = '\0'; @@ -455,9 +455,9 @@ int bgp_dump_attr(struct attr *attr, char *buf, size_t size) } if (strlen(buf) > 1) - return 1; + return true; else - return 0; + return false; } const char *bgp_notify_code_str(char code) @@ -561,8 +561,8 @@ static void bgp_debug_clear_updgrp_update_dbg(struct bgp *bgp) update_group_walk(bgp, update_group_clear_update_dbg, NULL); } -static int bgp_debug_print_evpn_prefix(struct vty *vty, const char *desc, - struct prefix *p) +static void bgp_debug_print_evpn_prefix(struct vty *vty, const char *desc, + struct prefix *p) { char evpn_desc[PREFIX2STR_BUFFER + INET_ADDRSTRLEN]; char buf[PREFIX2STR_BUFFER]; @@ -601,8 +601,6 @@ static int bgp_debug_print_evpn_prefix(struct vty *vty, const char *desc, } vty_out(vty, "%s %s\n", desc, evpn_desc); - - return 0; } static int bgp_debug_parse_evpn_prefix(struct vty *vty, struct cmd_token **argv, @@ -2491,8 +2489,8 @@ int bgp_debug_keepalive(struct peer *peer) bgp_debug_keepalive_peers); } -int bgp_debug_update(struct peer *peer, struct prefix *p, - struct update_group *updgrp, unsigned int inbound) +bool bgp_debug_update(struct peer *peer, struct prefix *p, + struct update_group *updgrp, unsigned int inbound) { char *host = NULL; @@ -2503,7 +2501,7 @@ int bgp_debug_update(struct peer *peer, struct prefix *p, if (bgp_debug_per_peer(host, term_bgp_debug_update, BGP_DEBUG_UPDATE_IN, bgp_debug_update_in_peers)) - return 1; + return true; } /* outbound */ @@ -2511,12 +2509,12 @@ int bgp_debug_update(struct peer *peer, struct prefix *p, if (bgp_debug_per_peer(host, term_bgp_debug_update, BGP_DEBUG_UPDATE_OUT, bgp_debug_update_out_peers)) - return 1; + return true; /* Check if update debugging implicitly enabled for the group. */ if (updgrp && UPDGRP_DBG_ON(updgrp)) - return 1; + return true; } @@ -2524,34 +2522,34 @@ int bgp_debug_update(struct peer *peer, struct prefix *p, if (bgp_debug_per_prefix(p, term_bgp_debug_update, BGP_DEBUG_UPDATE_PREFIX, bgp_debug_update_prefixes)) - return 1; + return true; } - return 0; + return false; } -int bgp_debug_bestpath(struct prefix *p) +bool bgp_debug_bestpath(struct prefix *p) { if (BGP_DEBUG(bestpath, BESTPATH)) { if (bgp_debug_per_prefix(p, term_bgp_debug_bestpath, BGP_DEBUG_BESTPATH, bgp_debug_bestpath_prefixes)) - return 1; + return true; } - return 0; + return false; } -int bgp_debug_zebra(struct prefix *p) +bool bgp_debug_zebra(struct prefix *p) { if (BGP_DEBUG(zebra, ZEBRA)) { if (bgp_debug_per_prefix(p, term_bgp_debug_zebra, BGP_DEBUG_ZEBRA, bgp_debug_zebra_prefixes)) - return 1; + return true; } - return 0; + return false; } const char *bgp_debug_rdpfxpath2str(afi_t afi, safi_t safi, diff --git a/bgpd/bgp_debug.h b/bgpd/bgp_debug.h index 1e6482e969..73007fe819 100644 --- a/bgpd/bgp_debug.h +++ b/bgpd/bgp_debug.h @@ -157,8 +157,8 @@ struct bgp_debug_filter { extern const char *const bgp_type_str[]; -extern int bgp_dump_attr(struct attr *, char *, size_t); -extern int bgp_debug_peer_updout_enabled(char *host); +extern bool bgp_dump_attr(struct attr *, char *, size_t); +extern bool bgp_debug_peer_updout_enabled(char *host); extern const char *bgp_notify_code_str(char); extern const char *bgp_notify_subcode_str(char, char); extern void bgp_notify_print(struct peer *, struct bgp_notify *, const char *); @@ -166,10 +166,10 @@ extern void bgp_notify_print(struct peer *, struct bgp_notify *, const char *); extern const struct message bgp_status_msg[]; extern int bgp_debug_neighbor_events(struct peer *peer); extern int bgp_debug_keepalive(struct peer *peer); -extern int bgp_debug_update(struct peer *peer, struct prefix *p, - struct update_group *updgrp, unsigned int inbound); -extern int bgp_debug_bestpath(struct prefix *p); -extern int bgp_debug_zebra(struct prefix *p); +extern bool bgp_debug_update(struct peer *peer, struct prefix *p, + struct update_group *updgrp, unsigned int inbound); +extern bool bgp_debug_bestpath(struct prefix *p); +extern bool bgp_debug_zebra(struct prefix *p); extern const char *bgp_debug_rdpfxpath2str(afi_t, safi_t, struct prefix_rd *, union prefixconstptr, mpls_label_t *, diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index 2711cf7a69..21bfe3f126 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -75,7 +75,7 @@ static void ecommunity_hash_free(struct ecommunity *ecom) structure, we don't add the value. Newly added value is sorted by numerical order. When the value is added to the structure return 1 else return 0. */ -int ecommunity_add_val(struct ecommunity *ecom, struct ecommunity_val *eval) +bool ecommunity_add_val(struct ecommunity *ecom, struct ecommunity_val *eval) { int c; @@ -84,7 +84,7 @@ int ecommunity_add_val(struct ecommunity *ecom, struct ecommunity_val *eval) ecom->size = 1; ecom->val = XCALLOC(MTYPE_ECOMMUNITY_VAL, ECOMMUNITY_SIZE); memcpy(ecom->val, eval->val, ECOMMUNITY_SIZE); - return 1; + return true; } /* If the value already exists in the structure return 0. */ @@ -93,7 +93,7 @@ int ecommunity_add_val(struct ecommunity *ecom, struct ecommunity_val *eval) p += ECOMMUNITY_SIZE, c++) { int ret = memcmp(p, eval->val, ECOMMUNITY_SIZE); if (ret == 0) - return 0; + return false; else if (ret > 0) break; } @@ -108,7 +108,7 @@ int ecommunity_add_val(struct ecommunity *ecom, struct ecommunity_val *eval) (ecom->size - 1 - c) * ECOMMUNITY_SIZE); memcpy(ecom->val + (c * ECOMMUNITY_SIZE), eval->val, ECOMMUNITY_SIZE); - return 1; + return true; } /* This function takes pointer to Extended Communites strucutre then @@ -837,20 +837,20 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter) return str_buf; } -int ecommunity_match(const struct ecommunity *ecom1, - const struct ecommunity *ecom2) +bool ecommunity_match(const struct ecommunity *ecom1, + const struct ecommunity *ecom2) { int i = 0; int j = 0; if (ecom1 == NULL && ecom2 == NULL) - return 1; + return true; if (ecom1 == NULL || ecom2 == NULL) - return 0; + return false; if (ecom1->size < ecom2->size) - return 0; + return false; /* Every community on com2 needs to be on com1 for this to match */ while (i < ecom1->size && j < ecom2->size) { @@ -862,9 +862,9 @@ int ecommunity_match(const struct ecommunity *ecom1, } if (j == ecom2->size) - return 1; + return true; else - return 0; + return false; } /* return first occurence of type */ @@ -889,54 +889,63 @@ extern struct ecommunity_val *ecommunity_lookup(const struct ecommunity *ecom, /* remove ext. community matching type and subtype * return 1 on success ( removed ), 0 otherwise (not present) */ -extern int ecommunity_strip(struct ecommunity *ecom, uint8_t type, - uint8_t subtype) +extern bool ecommunity_strip(struct ecommunity *ecom, uint8_t type, + uint8_t subtype) { - uint8_t *p; + uint8_t *p, *q, *new; int c, found = 0; /* When this is fist value, just add it. */ - if (ecom == NULL || ecom->val == NULL) { - return 0; - } + if (ecom == NULL || ecom->val == NULL) + return false; - /* If the value already exists in the structure return 0. */ + /* Check if any existing ext community matches. */ + /* Certain extended communities like the Route Target can be present + * multiple times, handle that. + */ c = 0; for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) { - if (p[0] == type && p[1] == subtype) { - found = 1; - break; - } + if (p[0] == type && p[1] == subtype) + found++; } + /* If no matching ext community exists, return. */ if (found == 0) - return 0; - /* Strip The selected value */ - ecom->size--; - /* size is reduced. no memmove to do */ - p = XMALLOC(MTYPE_ECOMMUNITY_VAL, ecom->size * ECOMMUNITY_SIZE); - if (c != 0) - memcpy(p, ecom->val, c * ECOMMUNITY_SIZE); - if ((ecom->size - c) != 0) - memcpy(p + (c)*ECOMMUNITY_SIZE, - ecom->val + (c + 1) * ECOMMUNITY_SIZE, - (ecom->size - c) * ECOMMUNITY_SIZE); - /* shift last ecommunities */ - XFREE(MTYPE_ECOMMUNITY, ecom->val); - ecom->val = p; - return 1; + return false; + + /* Handle the case where everything needs to be stripped. */ + if (found == ecom->size) { + XFREE(MTYPE_ECOMMUNITY_VAL, ecom->val); + ecom->size = 0; + return true; + } + + /* Strip matching ext community(ies). */ + new = XMALLOC(MTYPE_ECOMMUNITY_VAL, + (ecom->size - found) * ECOMMUNITY_SIZE); + q = new; + for (c = 0, p = ecom->val; c < ecom->size; c++, p += ECOMMUNITY_SIZE) { + if (!(p[0] == type && p[1] == subtype)) { + memcpy(q, p, ECOMMUNITY_SIZE); + q += ECOMMUNITY_SIZE; + } + } + XFREE(MTYPE_ECOMMUNITY_VAL, ecom->val); + ecom->val = new; + ecom->size -= found; + return true; } /* * Remove specified extended community value from extended community. * Returns 1 if value was present (and hence, removed), 0 otherwise. */ -int ecommunity_del_val(struct ecommunity *ecom, struct ecommunity_val *eval) +bool ecommunity_del_val(struct ecommunity *ecom, struct ecommunity_val *eval) { uint8_t *p; int c, found = 0; /* Make sure specified value exists. */ if (ecom == NULL || ecom->val == NULL) - return 0; + return false; c = 0; for (p = ecom->val; c < ecom->size; p += ECOMMUNITY_SIZE, c++) { if (!memcmp(p, eval->val, ECOMMUNITY_SIZE)) { @@ -945,7 +954,7 @@ int ecommunity_del_val(struct ecommunity *ecom, struct ecommunity_val *eval) } } if (found == 0) - return 0; + return false; /* Delete the selected value */ ecom->size--; @@ -958,7 +967,7 @@ int ecommunity_del_val(struct ecommunity *ecom, struct ecommunity_val *eval) (ecom->size - c) * ECOMMUNITY_SIZE); XFREE(MTYPE_ECOMMUNITY_VAL, ecom->val); ecom->val = p; - return 1; + return true; } int ecommunity_fill_pbr_action(struct ecommunity_val *ecom_eval, diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h index ae64f41ca1..df0da091d0 100644 --- a/bgpd/bgp_ecommunity.h +++ b/bgpd/bgp_ecommunity.h @@ -165,22 +165,22 @@ extern unsigned int ecommunity_hash_make(const void *); extern struct ecommunity *ecommunity_str2com(const char *, int, int); extern char *ecommunity_ecom2str(struct ecommunity *, int, int); extern void ecommunity_strfree(char **s); -extern int ecommunity_match(const struct ecommunity *, - const struct ecommunity *); +extern bool ecommunity_match(const struct ecommunity *, + const struct ecommunity *); extern char *ecommunity_str(struct ecommunity *); extern struct ecommunity_val *ecommunity_lookup(const struct ecommunity *, uint8_t, uint8_t); -extern int ecommunity_add_val(struct ecommunity *ecom, - struct ecommunity_val *eval); +extern bool ecommunity_add_val(struct ecommunity *ecom, + struct ecommunity_val *eval); /* for vpn */ extern struct ecommunity *ecommunity_new(void); -extern int ecommunity_add_val(struct ecommunity *, struct ecommunity_val *); -extern int ecommunity_strip(struct ecommunity *ecom, uint8_t type, - uint8_t subtype); +extern bool ecommunity_add_val(struct ecommunity *, struct ecommunity_val *); +extern bool ecommunity_strip(struct ecommunity *ecom, uint8_t type, + uint8_t subtype); extern struct ecommunity *ecommunity_new(void); -extern int ecommunity_del_val(struct ecommunity *ecom, - struct ecommunity_val *eval); +extern bool ecommunity_del_val(struct ecommunity *ecom, + struct ecommunity_val *eval); struct bgp_pbr_entry_action; extern int ecommunity_fill_pbr_action(struct ecommunity_val *ecom_eval, struct bgp_pbr_entry_action *api); @@ -202,4 +202,13 @@ extern void bgp_remove_ecomm_from_aggregate_hash( struct ecommunity *ecommunity); extern void bgp_aggr_ecommunity_remove(void *arg); + +static inline void ecommunity_strip_rts(struct ecommunity *ecom) +{ + uint8_t subtype = ECOMMUNITY_ROUTE_TARGET; + + ecommunity_strip(ecom, ECOMMUNITY_ENCODE_AS, subtype); + ecommunity_strip(ecom, ECOMMUNITY_ENCODE_IP, subtype); + ecommunity_strip(ecom, ECOMMUNITY_ENCODE_AS4, subtype); +} #endif /* _QUAGGA_BGP_ECOMMUNITY_H */ diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 664d62fd11..c3a9527b66 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -4576,16 +4576,34 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi, /* apply the route-map */ if (bgp_vrf->adv_cmd_rmap[afi][safi].map) { route_map_result_t ret; + struct bgp_path_info tmp_pi; + struct bgp_path_info_extra tmp_pie; + struct attr tmp_attr; + + tmp_attr = *pi->attr; + + /* Fill temp path_info */ + prep_for_rmap_apply( + &tmp_pi, &tmp_pie, rn, pi, + pi->peer, &tmp_attr); + + RESET_FLAG(tmp_attr.rmap_change_flags); ret = route_map_apply( bgp_vrf->adv_cmd_rmap[afi][safi] .map, - &rn->p, RMAP_BGP, pi); - if (ret == RMAP_DENYMATCH) + &rn->p, RMAP_BGP, &tmp_pi); + if (ret == RMAP_DENYMATCH) { + bgp_attr_flush(&tmp_attr); continue; - } - bgp_evpn_advertise_type5_route( - bgp_vrf, &rn->p, pi->attr, afi, safi); + } + bgp_evpn_advertise_type5_route( + bgp_vrf, &rn->p, &tmp_attr, + afi, safi); + } else + bgp_evpn_advertise_type5_route( + bgp_vrf, &rn->p, pi->attr, + afi, safi); break; } } diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 7ed37319b1..4f9d2a7b53 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -2210,13 +2210,13 @@ static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni) * appropriate action) and the VNI marked as unconfigured; the * VNI will continue to exist, purely as a "learnt" entity. */ -static int evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn) +static void evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn) { assert(bgp->vnihash); if (!is_vni_live(vpn)) { bgp_evpn_free(bgp, vpn); - return 0; + return; } /* We need to take the unconfigure action for each parameter of this VNI @@ -2234,8 +2234,6 @@ static int evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn) /* Next, deal with the import side. */ if (is_import_rt_configured(vpn)) evpn_unconfigure_import_rt(bgp, vpn, NULL); - - return 0; } /* diff --git a/bgpd/bgp_filter.c b/bgpd/bgp_filter.c index a03551e79d..7de8dc2c80 100644 --- a/bgpd/bgp_filter.c +++ b/bgpd/bgp_filter.c @@ -302,12 +302,9 @@ static void as_list_delete(struct as_list *aslist) as_list_free(aslist); } -static int as_list_empty(struct as_list *aslist) +static bool as_list_empty(struct as_list *aslist) { - if (aslist->head == NULL && aslist->tail == NULL) - return 1; - else - return 0; + return aslist->head == NULL && aslist->tail == NULL; } static void as_list_filter_delete(struct as_list *aslist, @@ -337,11 +334,9 @@ static void as_list_filter_delete(struct as_list *aslist, XFREE(MTYPE_AS_STR, name); } -static int as_filter_match(struct as_filter *asfilter, struct aspath *aspath) +static bool as_filter_match(struct as_filter *asfilter, struct aspath *aspath) { - if (bgp_regexec(asfilter->reg, aspath) != REG_NOMATCH) - return 1; - return 0; + return bgp_regexec(asfilter->reg, aspath) != REG_NOMATCH; } /* Apply AS path filter to AS. */ @@ -374,26 +369,25 @@ void as_list_delete_hook(void (*func)(const char *)) as_list_master.delete_hook = func; } -static int as_list_dup_check(struct as_list *aslist, struct as_filter *new) +static bool as_list_dup_check(struct as_list *aslist, struct as_filter *new) { struct as_filter *asfilter; for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) { if (asfilter->type == new->type && strcmp(asfilter->reg_str, new->reg_str) == 0) - return 1; + return true; } - return 0; + return false; } -int config_bgp_aspath_validate(const char *regstr) +bool config_bgp_aspath_validate(const char *regstr) { char valid_chars[] = "1234567890_^|[,{}() ]$*+.?-\\"; if (strspn(regstr, valid_chars) == strlen(regstr)) - return 1; - - return 0; + return true; + return false; } DEFUN(as_path, bgp_as_path_cmd, diff --git a/bgpd/bgp_filter.h b/bgpd/bgp_filter.h index 3c49e357ff..9357a2d382 100644 --- a/bgpd/bgp_filter.h +++ b/bgpd/bgp_filter.h @@ -31,6 +31,6 @@ extern enum as_filter_type as_list_apply(struct as_list *, void *); extern struct as_list *as_list_lookup(const char *); extern void as_list_add_hook(void (*func)(char *)); extern void as_list_delete_hook(void (*func)(const char *)); -extern int config_bgp_aspath_validate(const char *regstr); +extern bool config_bgp_aspath_validate(const char *regstr); #endif /* _QUAGGA_BGP_FILTER_H */ diff --git a/bgpd/bgp_flowspec_util.c b/bgpd/bgp_flowspec_util.c index 002aae561a..c117d08bfb 100644 --- a/bgpd/bgp_flowspec_util.c +++ b/bgpd/bgp_flowspec_util.c @@ -599,8 +599,8 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len, } /* 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) +bool bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi, + struct prefix *p) { struct bgp_pbr_entry_main api; int i; @@ -609,7 +609,7 @@ int bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi, memset(&api, 0, sizeof(struct bgp_pbr_entry_main)); if (bgp_pbr_build_and_validate_entry(&rn->p, pi, &api) < 0) - return 1; + return true; for (i = 0; i < api.action_num; i++) { api_action = &api.actions[i]; if (api_action->action != ACTION_REDIRECT_IP) @@ -617,7 +617,7 @@ int bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi, p->family = AF_INET; p->prefixlen = IPV4_MAX_BITLEN; p->u.prefix4 = api_action->u.zr.redirect_ip_v4; - return 0; + return false; } - return 1; + return true; } diff --git a/bgpd/bgp_flowspec_util.h b/bgpd/bgp_flowspec_util.h index 2ce911da4e..bd89176bec 100644 --- a/bgpd/bgp_flowspec_util.h +++ b/bgpd/bgp_flowspec_util.h @@ -54,8 +54,7 @@ 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); +extern bool 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_fsm.c b/bgpd/bgp_fsm.c index 0051b8d606..fdffe374c0 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -130,8 +130,8 @@ static struct peer *peer_xfer_conn(struct peer *from_peer) afi_t afi; safi_t safi; int fd; - int status, pstatus; - unsigned char last_evt, last_maj_evt; + enum bgp_fsm_status status, pstatus; + enum bgp_fsm_events last_evt, last_maj_evt; assert(from_peer != NULL); @@ -456,6 +456,10 @@ void bgp_timer_set(struct peer *peer) bgp_keepalives_off(peer); BGP_TIMER_OFF(peer->t_routeadv); break; + case BGP_STATUS_MAX: + flog_err(EC_LIB_DEVELOPMENT, + "BGP_STATUS_MAX while a legal state is not valid state for the FSM"); + break; } } @@ -660,32 +664,29 @@ static int bgp_graceful_deferral_timer_expire(struct thread *thread) return bgp_best_path_select_defer(bgp, afi, safi); } -static int bgp_update_delay_applicable(struct bgp *bgp) +static bool bgp_update_delay_applicable(struct bgp *bgp) { /* update_delay_over flag should be reset (set to 0) for any new applicability of the update-delay during BGP process lifetime. And it should be set after an occurence of the update-delay is over)*/ if (!bgp->update_delay_over) - return 1; - - return 0; + return true; + return false; } -int bgp_update_delay_active(struct bgp *bgp) +bool bgp_update_delay_active(struct bgp *bgp) { if (bgp->t_update_delay) - return 1; - - return 0; + return true; + return false; } -int bgp_update_delay_configured(struct bgp *bgp) +bool bgp_update_delay_configured(struct bgp *bgp) { if (bgp->v_update_delay) - return 1; - - return 0; + return true; + return false; } /* Do the post-processing needed when bgp comes out of the read-only mode @@ -836,28 +837,25 @@ void bgp_adjust_routeadv(struct peer *peer) } } -static int bgp_maxmed_onstartup_applicable(struct bgp *bgp) +static bool bgp_maxmed_onstartup_applicable(struct bgp *bgp) { if (!bgp->maxmed_onstartup_over) - return 1; - - return 0; + return true; + return false; } -int bgp_maxmed_onstartup_configured(struct bgp *bgp) +bool bgp_maxmed_onstartup_configured(struct bgp *bgp) { if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED) - return 1; - - return 0; + return true; + return false; } -int bgp_maxmed_onstartup_active(struct bgp *bgp) +bool bgp_maxmed_onstartup_active(struct bgp *bgp) { if (bgp->t_maxmed_onstartup) - return 1; - - return 0; + return true; + return false; } void bgp_maxmed_update(struct bgp *bgp) @@ -1956,8 +1954,7 @@ static int bgp_establish(struct peer *peer) hash_release(peer->bgp->peerhash, peer); hash_get(peer->bgp->peerhash, peer, hash_alloc_intern); - bgp_bfd_deregister_peer(peer); - bgp_bfd_register_peer(peer); + bgp_bfd_reset_peer(peer); return ret; } @@ -2038,7 +2035,7 @@ void bgp_fsm_event_update(struct peer *peer, int valid) /* Finite State Machine structure */ static const struct { int (*func)(struct peer *); - int next_state; + enum bgp_fsm_status next_state; } FSM[BGP_STATUS_MAX - 1][BGP_EVENTS_MAX - 1] = { { /* Idle state: In Idle state, all events other than BGP_Start is @@ -2185,7 +2182,7 @@ static const struct { /* Execute event process. */ int bgp_event(struct thread *thread) { - int event; + enum bgp_fsm_events event; struct peer *peer; int ret; @@ -2197,9 +2194,9 @@ int bgp_event(struct thread *thread) return (ret); } -int bgp_event_update(struct peer *peer, int event) +int bgp_event_update(struct peer *peer, enum bgp_fsm_events event) { - int next; + enum bgp_fsm_status next; int ret = 0; struct peer *other; int passive_conn = 0; diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h index 4b8db161d7..2fd5f6fc47 100644 --- a/bgpd/bgp_fsm.h +++ b/bgpd/bgp_fsm.h @@ -111,7 +111,7 @@ /* Prototypes. */ extern void bgp_fsm_event_update(struct peer *peer, int valid); extern int bgp_event(struct thread *); -extern int bgp_event_update(struct peer *, int event); +extern int bgp_event_update(struct peer *, enum bgp_fsm_events event); extern int bgp_stop(struct peer *peer); extern void bgp_timer_set(struct peer *); extern int bgp_routeadv_timer(struct thread *); @@ -119,8 +119,8 @@ extern void bgp_fsm_change_status(struct peer *peer, int status); extern const char *const peer_down_str[]; extern void bgp_update_delay_end(struct bgp *); extern void bgp_maxmed_update(struct bgp *); -extern int bgp_maxmed_onstartup_configured(struct bgp *); -extern int bgp_maxmed_onstartup_active(struct bgp *); +extern bool bgp_maxmed_onstartup_configured(struct bgp *); +extern bool bgp_maxmed_onstartup_active(struct bgp *); extern int bgp_fsm_error_subcode(int status); /** diff --git a/bgpd/bgp_lcommunity.c b/bgpd/bgp_lcommunity.c index 7a4435f6f2..324505418c 100644 --- a/bgpd/bgp_lcommunity.c +++ b/bgpd/bgp_lcommunity.c @@ -59,8 +59,8 @@ static void lcommunity_hash_free(struct lcommunity *lcom) structure, we don't add the value. Newly added value is sorted by numerical order. When the value is added to the structure return 1 else return 0. */ -static int lcommunity_add_val(struct lcommunity *lcom, - struct lcommunity_val *lval) +static bool lcommunity_add_val(struct lcommunity *lcom, + struct lcommunity_val *lval) { uint8_t *p; int ret; @@ -71,7 +71,7 @@ static int lcommunity_add_val(struct lcommunity *lcom, lcom->size++; lcom->val = XMALLOC(MTYPE_LCOMMUNITY_VAL, lcom_length(lcom)); memcpy(lcom->val, lval->val, LCOMMUNITY_SIZE); - return 1; + return true; } /* If the value already exists in the structure return 0. */ @@ -79,7 +79,7 @@ static int lcommunity_add_val(struct lcommunity *lcom, for (p = lcom->val; c < lcom->size; p += LCOMMUNITY_SIZE, c++) { ret = memcmp(p, lval->val, LCOMMUNITY_SIZE); if (ret == 0) - return 0; + return false; if (ret > 0) break; } @@ -94,7 +94,7 @@ static int lcommunity_add_val(struct lcommunity *lcom, (lcom->size - 1 - c) * LCOMMUNITY_SIZE); memcpy(lcom->val + c * LCOMMUNITY_SIZE, lval->val, LCOMMUNITY_SIZE); - return 1; + return true; } /* This function takes pointer to Large Communites strucutre then @@ -456,7 +456,7 @@ struct lcommunity *lcommunity_str2com(const char *str) return lcom; } -int lcommunity_include(struct lcommunity *lcom, uint8_t *ptr) +bool lcommunity_include(struct lcommunity *lcom, uint8_t *ptr) { int i; uint8_t *lcom_ptr; @@ -464,25 +464,25 @@ int lcommunity_include(struct lcommunity *lcom, uint8_t *ptr) for (i = 0; i < lcom->size; i++) { lcom_ptr = lcom->val + (i * LCOMMUNITY_SIZE); if (memcmp(ptr, lcom_ptr, LCOMMUNITY_SIZE) == 0) - return 1; + return true; } - return 0; + return false; } -int lcommunity_match(const struct lcommunity *lcom1, - const struct lcommunity *lcom2) +bool lcommunity_match(const struct lcommunity *lcom1, + const struct lcommunity *lcom2) { int i = 0; int j = 0; if (lcom1 == NULL && lcom2 == NULL) - return 1; + return true; if (lcom1 == NULL || lcom2 == NULL) - return 0; + return false; if (lcom1->size < lcom2->size) - return 0; + return false; /* Every community on com2 needs to be on com1 for this to match */ while (i < lcom1->size && j < lcom2->size) { @@ -494,9 +494,9 @@ int lcommunity_match(const struct lcommunity *lcom1, } if (j == lcom2->size) - return 1; + return true; else - return 0; + return false; } /* Delete one lcommunity. */ diff --git a/bgpd/bgp_lcommunity.h b/bgpd/bgp_lcommunity.h index 7d63f4d26a..e10ab0eef1 100644 --- a/bgpd/bgp_lcommunity.h +++ b/bgpd/bgp_lcommunity.h @@ -66,10 +66,10 @@ extern void lcommunity_unintern(struct lcommunity **); extern unsigned int lcommunity_hash_make(const void *); extern struct hash *lcommunity_hash(void); extern struct lcommunity *lcommunity_str2com(const char *); -extern int lcommunity_match(const struct lcommunity *, - const struct lcommunity *); +extern bool lcommunity_match(const struct lcommunity *, + const struct lcommunity *); extern char *lcommunity_str(struct lcommunity *, bool make_json); -extern int lcommunity_include(struct lcommunity *lcom, uint8_t *ptr); +extern bool lcommunity_include(struct lcommunity *lcom, uint8_t *ptr); extern void lcommunity_del_val(struct lcommunity *lcom, uint8_t *ptr); extern void bgp_compute_aggregate_lcommunity( diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 8758d0ca78..3e2ba9802a 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -385,13 +385,13 @@ int vpn_leak_label_callback( return 0; } -static int ecom_intersect(struct ecommunity *e1, struct ecommunity *e2) +static bool ecom_intersect(struct ecommunity *e1, struct ecommunity *e2) { int i; int j; if (!e1 || !e2) - return 0; + return false; for (i = 0; i < e1->size; ++i) { for (j = 0; j < e2->size; ++j) { @@ -399,11 +399,11 @@ static int ecom_intersect(struct ecommunity *e1, struct ecommunity *e2) e2->val + (j * ECOMMUNITY_SIZE), ECOMMUNITY_SIZE)) { - return 1; + return true; } } } - return 0; + return false; } static bool labels_same(struct bgp_path_info *bpi, mpls_label_t *label, @@ -744,10 +744,15 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ struct ecommunity *old_ecom; struct ecommunity *new_ecom; + /* Export with the 'from' instance's export RTs. */ + /* If doing VRF-to-VRF leaking, strip existing RTs first. */ old_ecom = static_attr.ecommunity; if (old_ecom) { - new_ecom = ecommunity_merge( - ecommunity_dup(old_ecom), + new_ecom = ecommunity_dup(old_ecom); + if (CHECK_FLAG(bgp_vrf->af_flags[afi][SAFI_UNICAST], + BGP_CONFIG_VRF_TO_VRF_EXPORT)) + ecommunity_strip_rts(new_ecom); + new_ecom = ecommunity_merge(new_ecom, bgp_vrf->vpn_policy[afi] .rtlist[BGP_VPN_POLICY_DIR_TOVPN]); if (!old_ecom->refcnt) @@ -1087,6 +1092,20 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ /* shallow copy */ static_attr = *path_vpn->attr; + struct ecommunity *old_ecom; + struct ecommunity *new_ecom; + + /* If doing VRF-to-VRF leaking, strip RTs. */ + old_ecom = static_attr.ecommunity; + if (old_ecom && CHECK_FLAG(bgp_vrf->af_flags[afi][safi], + BGP_CONFIG_VRF_TO_VRF_IMPORT)) { + new_ecom = ecommunity_dup(old_ecom); + ecommunity_strip_rts(new_ecom); + static_attr.ecommunity = new_ecom; + if (!old_ecom->refcnt) + ecommunity_free(&old_ecom); + } + /* * Nexthop: stash and clear * diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index ab0c3a3f11..23c5adbf28 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -470,8 +470,8 @@ static void bgp_connected_cleanup(struct route_table *table, } } -int bgp_nexthop_self(struct bgp *bgp, afi_t afi, uint8_t type, uint8_t sub_type, - struct attr *attr, struct bgp_node *rn) +bool bgp_nexthop_self(struct bgp *bgp, afi_t afi, uint8_t type, + uint8_t sub_type, struct attr *attr, struct bgp_node *rn) { uint8_t new_afi = afi == AFI_IP ? AF_INET : AF_INET6; struct bgp_addr tmp_addr = {{0}}, *addr = NULL; @@ -505,7 +505,7 @@ int bgp_nexthop_self(struct bgp *bgp, afi_t afi, uint8_t type, uint8_t sub_type, attr->mp_nexthop_global_in; tmp_addr.p.prefixlen = IPV4_MAX_BITLEN; } else - return 0; + return false; } break; case AF_INET6: @@ -523,7 +523,7 @@ int bgp_nexthop_self(struct bgp *bgp, afi_t afi, uint8_t type, uint8_t sub_type, addr = hash_lookup(bgp->address_hash, &tmp_addr); if (addr) - return 1; + return true; if (new_afi == AF_INET) { memset(&tmp_tip, 0, sizeof(struct tip_addr)); @@ -539,13 +539,13 @@ int bgp_nexthop_self(struct bgp *bgp, afi_t afi, uint8_t type, uint8_t sub_type, tip = hash_lookup(bgp->tip_hash, &tmp_tip); if (tip) - return 1; + return true; } - return 0; + return false; } -int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer) +bool bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer) { struct bgp_node *rn1; struct bgp_node *rn2; @@ -558,7 +558,7 @@ int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer) rn1 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p); if (!rn1) - return 0; + return false; p.family = AF_INET; p.prefixlen = IPV4_MAX_BITLEN; @@ -567,18 +567,18 @@ int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer) rn2 = bgp_node_match(peer->bgp->connected_table[AFI_IP], &p); if (!rn2) { bgp_unlock_node(rn1); - return 0; + return false; } - ret = (rn1 == rn2) ? 1 : 0; + ret = (rn1 == rn2); bgp_unlock_node(rn1); bgp_unlock_node(rn2); - return (ret); + return ret; } -int bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer) +bool bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer) { struct bgp_node *rn1; struct bgp_node *rn2; @@ -591,7 +591,7 @@ int bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer) rn1 = bgp_node_match(peer->bgp->connected_table[AFI_IP6], &p); if (!rn1) - return 0; + return false; p.family = AF_INET6; p.prefixlen = IPV6_MAX_BITLEN; @@ -600,10 +600,10 @@ int bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer) rn2 = bgp_node_match(peer->bgp->connected_table[AFI_IP6], &p); if (!rn2) { bgp_unlock_node(rn1); - return 0; + return false; } - ret = (rn1 == rn2) ? 1 : 0; + ret = (rn1 == rn2); bgp_unlock_node(rn1); bgp_unlock_node(rn2); @@ -611,8 +611,9 @@ int bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer) return ret; } -int bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop, - struct update_subgroup *subgrp) +bool bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop, + struct update_subgroup *subgrp, + struct peer *exclude) { struct bgp_node *rn1 = NULL, *rn2 = NULL; struct peer_af *paf = NULL; @@ -629,16 +630,19 @@ int bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop, bgp = SUBGRP_INST(subgrp); rn1 = bgp_node_match(bgp->connected_table[AFI_IP6], &np); if (!rn1) - return 0; + return false; SUBGRP_FOREACH_PEER (subgrp, paf) { + /* Skip peer we're told to exclude - e.g., source of route. */ + if (paf->peer == exclude) + continue; p.u.prefix6 = paf->peer->su.sin6.sin6_addr; rn2 = bgp_node_match(bgp->connected_table[AFI_IP6], &p); if (rn1 == rn2) { bgp_unlock_node(rn1); bgp_unlock_node(rn2); - return 1; + return true; } if (rn2) @@ -646,11 +650,12 @@ int bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop, } bgp_unlock_node(rn1); - return 0; + return false; } -int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop, - struct update_subgroup *subgrp) +bool bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop, + struct update_subgroup *subgrp, + struct peer *exclude) { struct bgp_node *rn1, *rn2; struct peer_af *paf; @@ -667,16 +672,20 @@ int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop, bgp = SUBGRP_INST(subgrp); rn1 = bgp_node_match(bgp->connected_table[AFI_IP], &np); if (!rn1) - return 0; + return false; SUBGRP_FOREACH_PEER (subgrp, paf) { + /* Skip peer we're told to exclude - e.g., source of route. */ + if (paf->peer == exclude) + continue; + p.u.prefix4 = paf->peer->su.sin.sin_addr; rn2 = bgp_node_match(bgp->connected_table[AFI_IP], &p); if (rn1 == rn2) { bgp_unlock_node(rn1); bgp_unlock_node(rn2); - return 1; + return true; } if (rn2) @@ -684,7 +693,7 @@ int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop, } bgp_unlock_node(rn1); - return 0; + return false; } static void bgp_show_nexthops_detail(struct vty *vty, struct bgp *bgp, diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h index af4c0bc047..461e772119 100644 --- a/bgpd/bgp_nexthop.h +++ b/bgpd/bgp_nexthop.h @@ -81,16 +81,19 @@ struct bgp_addrv6 { extern void bgp_connected_add(struct bgp *bgp, struct connected *c); extern void bgp_connected_delete(struct bgp *bgp, struct connected *c); -extern int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop, - struct update_subgroup *subgrp); -extern int bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop, - struct update_subgroup *subgrp); -extern int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer); -extern int bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer); +extern bool bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop, + struct update_subgroup *subgrp, + struct peer *exclude); +extern bool bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop, + struct update_subgroup *subgrp, + struct peer *exclude); +extern bool bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer); +extern bool bgp_multiaccess_check_v6(struct in6_addr nexthop, + struct peer *peer); extern int bgp_config_write_scan_time(struct vty *); -extern int bgp_nexthop_self(struct bgp *bgp, afi_t afi, uint8_t type, - uint8_t sub_type, struct attr *attr, - struct bgp_node *rn); +extern bool bgp_nexthop_self(struct bgp *bgp, afi_t afi, uint8_t type, + uint8_t sub_type, struct attr *attr, + struct bgp_node *rn); extern struct bgp_nexthop_cache *bnc_new(void); extern void bnc_free(struct bgp_nexthop_cache *bnc); extern void bnc_nexthop_free(struct bgp_nexthop_cache *bnc); diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 81bb45aa76..4a2f7d5882 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -1013,15 +1013,15 @@ static int bgp_auth_parse(struct peer *peer, size_t length) return -1; } -static int strict_capability_same(struct peer *peer) +static bool strict_capability_same(struct peer *peer) { int i, j; for (i = AFI_IP; i < AFI_MAX; i++) for (j = SAFI_UNICAST; j < SAFI_MAX; j++) if (peer->afc[i][j] != peer->afc_nego[i][j]) - return 0; - return 1; + return false; + return true; } /* peek into option, stores ASN to *as4 if the AS4 capability was found. diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index a7b2bc3458..10e96497fb 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -587,7 +587,7 @@ void bgp_open_send(struct peer *peer) * @param peer * @return 0 */ -static int bgp_write_notify(struct peer *peer) +static void bgp_write_notify(struct peer *peer) { int ret, val; uint8_t type; @@ -597,7 +597,7 @@ static int bgp_write_notify(struct peer *peer) s = stream_fifo_pop(peer->obuf); if (!s) - return 0; + return; assert(stream_get_endp(s) >= BGP_HEADER_SIZE); @@ -617,7 +617,7 @@ static int bgp_write_notify(struct peer *peer) if (ret <= 0) { stream_free(s); BGP_EVENT_ADD(peer, TCP_fatal_error); - return 0; + return; } /* Disable Nagle, make NOTIFY packet go out right away */ @@ -649,8 +649,6 @@ static int bgp_write_notify(struct peer *peer) BGP_EVENT_ADD(peer, BGP_Stop); stream_free(s); - - return 0; } /* @@ -1142,6 +1140,15 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size) return BGP_Stop; } + /* Codification of AS 0 Processing */ + if (remote_as == BGP_AS_ZERO) { + flog_err(EC_BGP_PKT_OPEN, "%s bad OPEN, got AS set to 0", + peer->host); + bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_BAD_PEER_AS); + return BGP_Stop; + } + if (remote_as == BGP_AS_TRANS) { /* Take the AS4 from the capability. We must have received the * capability now! Otherwise we have a asn16 peer who uses @@ -2328,7 +2335,7 @@ int bgp_process_packet(struct thread *thread) flog_err( EC_BGP_PKT_OPEN, "%s: BGP OPEN receipt failed for peer: %s", - __FUNCTION__, peer->host); + __func__, peer->host); break; case BGP_MSG_UPDATE: atomic_fetch_add_explicit(&peer->update_in, 1, @@ -2339,7 +2346,7 @@ int bgp_process_packet(struct thread *thread) flog_err( EC_BGP_UPDATE_RCV, "%s: BGP UPDATE receipt failed for peer: %s", - __FUNCTION__, peer->host); + __func__, peer->host); break; case BGP_MSG_NOTIFY: atomic_fetch_add_explicit(&peer->notify_in, 1, @@ -2349,7 +2356,7 @@ int bgp_process_packet(struct thread *thread) flog_err( EC_BGP_NOTIFY_RCV, "%s: BGP NOTIFY receipt failed for peer: %s", - __FUNCTION__, peer->host); + __func__, peer->host); break; case BGP_MSG_KEEPALIVE: peer->readtime = monotime(NULL); @@ -2360,7 +2367,7 @@ int bgp_process_packet(struct thread *thread) flog_err( EC_BGP_KEEP_RCV, "%s: BGP KEEPALIVE receipt failed for peer: %s", - __FUNCTION__, peer->host); + __func__, peer->host); break; case BGP_MSG_ROUTE_REFRESH_NEW: case BGP_MSG_ROUTE_REFRESH_OLD: @@ -2371,7 +2378,7 @@ int bgp_process_packet(struct thread *thread) flog_err( EC_BGP_RFSH_RCV, "%s: BGP ROUTEREFRESH receipt failed for peer: %s", - __FUNCTION__, peer->host); + __func__, peer->host); break; case BGP_MSG_CAPABILITY: atomic_fetch_add_explicit(&peer->dynamic_cap_in, 1, @@ -2381,7 +2388,7 @@ int bgp_process_packet(struct thread *thread) flog_err( EC_BGP_CAP_RCV, "%s: BGP CAPABILITY receipt failed for peer: %s", - __FUNCTION__, peer->host); + __func__, peer->host); break; default: /* Suppress uninitialized variable warning */ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 0806e1c680..265f122c23 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1282,30 +1282,30 @@ static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p, } /* If community attribute includes no_export then return 1. */ -static int bgp_community_filter(struct peer *peer, struct attr *attr) +static bool bgp_community_filter(struct peer *peer, struct attr *attr) { if (attr->community) { /* NO_ADVERTISE check. */ if (community_include(attr->community, COMMUNITY_NO_ADVERTISE)) - return 1; + return true; /* NO_EXPORT check. */ if (peer->sort == BGP_PEER_EBGP && community_include(attr->community, COMMUNITY_NO_EXPORT)) - return 1; + return true; /* NO_EXPORT_SUBCONFED check. */ if (peer->sort == BGP_PEER_EBGP || peer->sort == BGP_PEER_CONFED) if (community_include(attr->community, COMMUNITY_NO_EXPORT_SUBCONFED)) - return 1; + return true; } - return 0; + return false; } /* Route reflection loop check. */ -static int bgp_cluster_filter(struct peer *peer, struct attr *attr) +static bool bgp_cluster_filter(struct peer *peer, struct attr *attr) { struct in_addr cluster_id; @@ -1316,9 +1316,9 @@ static int bgp_cluster_filter(struct peer *peer, struct attr *attr) cluster_id = peer->bgp->router_id; if (cluster_loop_check(attr->cluster, cluster_id)) - return 1; + return true; } - return 0; + return false; } static int bgp_input_modifier(struct peer *peer, struct prefix *p, @@ -1543,9 +1543,9 @@ static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr) memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4); } -int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, - struct update_subgroup *subgrp, struct prefix *p, - struct attr *attr) +bool subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, + struct update_subgroup *subgrp, struct prefix *p, + struct attr *attr) { struct bgp_filter *filter; struct peer *from; @@ -1562,7 +1562,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, int samepeer_safe = 0; /* for synthetic mplsvpns routes */ if (DISABLE_BGP_ANNOUNCE) - return 0; + return false; afi = SUBGRP_AFI(subgrp); safi = SUBGRP_SAFI(subgrp); @@ -1609,7 +1609,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID) || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY) || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) { - return 0; + return false; } /* If this is not the bestpath then check to see if there is an enabled @@ -1617,14 +1617,14 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, * feature that requires us to advertise it */ if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) { if (!bgp_addpath_tx_path(peer->addpath_type[afi][safi], pi)) { - return 0; + return false; } } /* Aggregate-address suppress check. */ if (pi->extra && pi->extra->suppress) if (!UNSUPPRESS_MAP_NAME(filter)) { - return 0; + return false; } /* @@ -1635,7 +1635,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, */ if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK) - return 0; + return false; /* If it's labeled safi, make sure the route has a valid label. */ if (safi == SAFI_LABELED_UNICAST) { @@ -1648,13 +1648,13 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, inet_ntop(p->family, &p->u.prefix, buf, SU_ADDRSTRLEN), p->prefixlen, &label); - return 0; + return false; } } /* Do not send back route to sender. */ if (onlypeer && from == onlypeer) { - return 0; + return false; } /* Do not send the default route in the BGP table if the neighbor is @@ -1662,9 +1662,9 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)) { if (p->family == AF_INET && p->u.prefix4.s_addr == INADDR_ANY) - return 0; + return false; else if (p->family == AF_INET6 && p->prefixlen == 0) - return 0; + return false; } /* Transparency check. */ @@ -1679,7 +1679,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) zlog_debug( "subgrpannouncecheck: community filter check fail"); - return 0; + return false; } /* If the attribute has originator-id and it is same as remote @@ -1692,7 +1692,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, "remote router-id", onlypeer->host, prefix2str(p, buf, sizeof(buf))); - return 0; + return false; } /* ORF prefix-list filter check */ @@ -1710,7 +1710,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, peer->host, prefix2str(p, buf, sizeof(buf))); - return 0; + return false; } } @@ -1719,7 +1719,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) zlog_debug("%s [Update:SEND] %s is filtered", peer->host, prefix2str(p, buf, sizeof(buf))); - return 0; + return false; } /* AS path loop check. */ @@ -1730,7 +1730,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, "%s [Update:SEND] suppress announcement to peer AS %u " "that is part of AS path.", onlypeer->host, onlypeer->as); - return 0; + return false; } /* If we're a CONFED we need to loop check the CONFED ID too */ @@ -1741,7 +1741,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, "%s [Update:SEND] suppress announcement to peer AS %u" " is AS path.", peer->host, bgp->confed_id); - return 0; + return false; } } @@ -1765,13 +1765,13 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, BGP_FLAG_NO_CLIENT_TO_CLIENT)) if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) - return 0; + return false; } else { /* A route from a Non-client peer. Reflect to all other clients. */ if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) - return 0; + return false; } } @@ -1875,16 +1875,9 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, struct bgp_path_info_extra dummy_rmap_path_extra = {0}; struct attr dummy_attr = {0}; - memset(&rmap_path, 0, sizeof(struct bgp_path_info)); - rmap_path.peer = peer; - rmap_path.attr = attr; - rmap_path.net = rn; - - if (pi->extra) { - memcpy(&dummy_rmap_path_extra, pi->extra, - sizeof(struct bgp_path_info_extra)); - rmap_path.extra = &dummy_rmap_path_extra; - } + /* Fill temp path_info */ + prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, + rn, pi, peer, attr); /* don't confuse inbound and outbound setting */ RESET_FLAG(attr->rmap_change_flags); @@ -1917,7 +1910,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, peer->host, prefix2str(p, buf, sizeof(buf))); bgp_attr_flush(attr); - return 0; + return false; } } @@ -1933,7 +1926,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, if (peer->bgp->ebgp_requires_policy == DEFAULT_EBGP_POLICY_ENABLED) if (!bgp_outbound_policy_exists(peer, filter)) - return 0; + return false; /* draft-ietf-idr-deprecate-as-set-confed-set * Filter routes having AS_SET or AS_CONFED_SET in the path. @@ -1943,7 +1936,11 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, */ if (peer->bgp->reject_as_sets == BGP_REJECT_AS_SETS_ENABLED) if (aspath_check_as_sets(attr->aspath)) - return 0; + return false; + + /* Codification of AS 0 Processing */ + if (aspath_check_as_zero(attr->aspath)) + return 0; if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN)) { if (peer->sort == BGP_PEER_IBGP @@ -2002,7 +1999,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, if ((p->family == AF_INET) && (!bgp_subgrp_multiaccess_check_v4( piattr->nexthop, - subgrp))) + subgrp, from))) subgroup_announce_reset_nhop( (peer_cap_enhe(peer, afi, safi) ? AF_INET6 @@ -2012,7 +2009,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, if ((p->family == AF_INET6) && (!bgp_subgrp_multiaccess_check_v6( piattr->mp_nexthop_global, - subgrp))) + subgrp, from))) subgroup_announce_reset_nhop( (peer_cap_enhe(peer, afi, safi) ? AF_INET6 @@ -2051,7 +2048,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, subgroup_announce_reset_nhop(AF_INET6, attr); } - return 1; + return true; } static int bgp_route_select_timer_expire(struct thread *thread) @@ -2103,6 +2100,7 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, if (debug) prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf)); + rn->reason = bgp_path_selection_none; /* bgp deterministic-med */ new_select = NULL; if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) { @@ -2182,6 +2180,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, new_select = NULL; for (pi = bgp_node_get_bgp_path_info(rn); (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) { + enum bgp_path_selection_reason reason; + if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) old_select = pi; @@ -2222,8 +2222,12 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK); + reason = rn->reason; if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg, debug, pfx_buf, afi, safi, &rn->reason)) { + if (new_select == NULL && + reason != bgp_path_selection_none) + rn->reason = reason; new_select = pi; } } @@ -2309,10 +2313,10 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, * A new route/change in bestpath of an existing route. Evaluate the path * for advertisement to the subgroup. */ -int subgroup_process_announce_selected(struct update_subgroup *subgrp, - struct bgp_path_info *selected, - struct bgp_node *rn, - uint32_t addpath_tx_id) +void subgroup_process_announce_selected(struct update_subgroup *subgrp, + struct bgp_path_info *selected, + struct bgp_node *rn, + uint32_t addpath_tx_id) { struct prefix *p; struct peer *onlypeer; @@ -2336,7 +2340,7 @@ int subgroup_process_announce_selected(struct update_subgroup *subgrp, /* First update is deferred until ORF or ROUTE-REFRESH is received */ if (onlypeer && CHECK_FLAG(onlypeer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH)) - return 0; + return; memset(&attr, 0, sizeof(struct attr)); /* It's initialized in bgp_announce_check() */ @@ -2355,8 +2359,6 @@ int subgroup_process_announce_selected(struct update_subgroup *subgrp, else { bgp_adj_out_unset_subgroup(rn, subgrp, 1, addpath_tx_id); } - - return 0; } /* @@ -2380,8 +2382,8 @@ void bgp_zebra_clear_route_change_flags(struct bgp_node *rn) * if the route selection returns the same best route as earlier - to * determine if we need to update zebra or not. */ -int bgp_zebra_has_route_changed(struct bgp_node *rn, - struct bgp_path_info *selected) +bool bgp_zebra_has_route_changed(struct bgp_node *rn, + struct bgp_path_info *selected) { struct bgp_path_info *mpinfo; @@ -2393,7 +2395,7 @@ int bgp_zebra_has_route_changed(struct bgp_node *rn, */ if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED) || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)) - return 1; + return true; /* * If this is multipath, check all selected paths for any nexthop change @@ -2402,11 +2404,11 @@ int bgp_zebra_has_route_changed(struct bgp_node *rn, mpinfo = bgp_path_info_mpath_next(mpinfo)) { if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED) || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED)) - return 1; + return true; } /* Nothing has changed from the RIB's perspective. */ - return 0; + return false; } struct bgp_process_queue { @@ -2682,17 +2684,31 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, /* apply the route-map */ if (bgp->adv_cmd_rmap[afi][safi].map) { route_map_result_t ret; + struct bgp_path_info rmap_path; + struct bgp_path_info_extra rmap_path_extra; + struct attr dummy_attr; + + dummy_attr = *new_select->attr; + + /* Fill temp path_info */ + prep_for_rmap_apply( + &rmap_path, &rmap_path_extra, + rn, new_select, new_select->peer, + &dummy_attr); + + RESET_FLAG(dummy_attr.rmap_change_flags); ret = route_map_apply( bgp->adv_cmd_rmap[afi][safi].map, - &rn->p, RMAP_BGP, new_select); - if (ret == RMAP_PERMITMATCH) - bgp_evpn_advertise_type5_route( - bgp, &rn->p, new_select->attr, - afi, safi); - else + &rn->p, RMAP_BGP, &rmap_path); + if (ret == RMAP_DENYMATCH) { + bgp_attr_flush(&dummy_attr); bgp_evpn_withdraw_type5_route( bgp, &rn->p, afi, safi); + } else + bgp_evpn_advertise_type5_route( + bgp, &rn->p, &dummy_attr, + afi, safi); } else { bgp_evpn_advertise_type5_route(bgp, &rn->p, @@ -2930,20 +2946,20 @@ static int bgp_maximum_prefix_restart_timer(struct thread *thread) return 0; } -int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi, - int always) +bool bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi, + int always) { iana_afi_t pkt_afi; iana_safi_t pkt_safi; if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX)) - return 0; + return false; if (peer->pcount[afi][safi] > peer->pmax[afi][safi]) { if (CHECK_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT) && !always) - return 0; + return false; zlog_info( "%%MAXPFXEXCEED: No. of %s prefix received from %s %" PRIu32 @@ -2954,7 +2970,7 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi, if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)) - return 0; + return false; /* Convert AFI, SAFI to values for packet. */ pkt_afi = afi_int2iana(afi); @@ -2978,7 +2994,7 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi, /* Dynamic peers will just close their connection. */ if (peer_dynamic_neighbor(peer)) - return 1; + return true; /* restart timer start */ if (peer->pmax_restart[afi][safi]) { @@ -2995,7 +3011,7 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi, peer->v_pmax_restart); } - return 1; + return true; } else UNSET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_LIMIT); @@ -3005,7 +3021,7 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi, if (CHECK_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD) && !always) - return 0; + return false; zlog_info( "%%MAXPFX: No. of %s prefix received from %s reaches %" PRIu32 @@ -3017,7 +3033,7 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi, } else UNSET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_PREFIX_THRESHOLD); - return 0; + return false; } /* Unconditionally remove the route from the RIB, without taking @@ -3186,23 +3202,23 @@ static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path, } /* Check if received nexthop is valid or not. */ -static int bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi, - uint8_t type, uint8_t stype, - struct attr *attr, struct bgp_node *rn) +static bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi, + uint8_t type, uint8_t stype, + struct attr *attr, struct bgp_node *rn) { - int ret = 0; + bool ret = 0; /* Only validated for unicast and multicast currently. */ /* Also valid for EVPN where the nexthop is an IP address. */ if (safi != SAFI_UNICAST && safi != SAFI_MULTICAST && safi != SAFI_EVPN) - return 0; + return false; /* If NEXT_HOP is present, validate it. */ if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) { if (attr->nexthop.s_addr == INADDR_ANY || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr)) || bgp_nexthop_self(bgp, afi, type, stype, attr, rn)) - return 1; + return true; } /* If MP_NEXTHOP is present, validate it. */ @@ -3233,7 +3249,7 @@ static int bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi, break; default: - ret = 1; + ret = true; break; } } @@ -4592,30 +4608,30 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi) } } -int bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter) +bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter) { if (peer->sort == BGP_PEER_IBGP) - return 1; + return true; if (peer->sort == BGP_PEER_EBGP && (ROUTE_MAP_OUT_NAME(filter) || PREFIX_LIST_OUT_NAME(filter) || FILTER_LIST_OUT_NAME(filter) || DISTRIBUTE_OUT_NAME(filter))) - return 1; - return 0; + return true; + return false; } -int bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter) +bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter) { if (peer->sort == BGP_PEER_IBGP) - return 1; + return true; if (peer->sort == BGP_PEER_EBGP && (ROUTE_MAP_IN_NAME(filter) || PREFIX_LIST_IN_NAME(filter) || FILTER_LIST_IN_NAME(filter) || DISTRIBUTE_IN_NAME(filter))) - return 1; - return 0; + return true; + return false; } static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table, @@ -6005,11 +6021,11 @@ static void bgp_aggregate_free(struct bgp_aggregate *aggregate) XFREE(MTYPE_BGP_AGGREGATE, aggregate); } -static int bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin, - struct aspath *aspath, - struct community *comm, - struct ecommunity *ecomm, - struct lcommunity *lcomm) +static bool bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin, + struct aspath *aspath, + struct community *comm, + struct ecommunity *ecomm, + struct lcommunity *lcomm) { static struct aspath *ae = NULL; @@ -6017,27 +6033,27 @@ static int bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin, ae = aspath_empty(); if (!pi) - return 0; + return false; if (origin != pi->attr->origin) - return 0; + return false; if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae)) - return 0; + return false; if (!community_cmp(pi->attr->community, comm)) - return 0; + return false; if (!ecommunity_cmp(pi->attr->ecommunity, ecomm)) - return 0; + return false; if (!lcommunity_cmp(pi->attr->lcommunity, lcomm)) - return 0; + return false; if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)) - return 0; + return false; - return 1; + return true; } static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi, diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 0ad656d133..628c933c07 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -467,6 +467,23 @@ static inline bool is_pi_family_matching(struct bgp_path_info *pi, return false; } +static inline void prep_for_rmap_apply(struct bgp_path_info *dst_pi, + struct bgp_path_info_extra *dst_pie, + struct bgp_node *rn, + struct bgp_path_info *src_pi, + struct peer *peer, struct attr *attr) +{ + memset(dst_pi, 0, sizeof(struct bgp_path_info)); + dst_pi->peer = peer; + dst_pi->attr = attr; + dst_pi->net = rn; + if (src_pi->extra) { + memcpy(dst_pie, src_pi->extra, + sizeof(struct bgp_path_info_extra)); + dst_pi->extra = dst_pie; + } +} + /* called before bgp_process() */ DECLARE_HOOK(bgp_process, (struct bgp *bgp, afi_t afi, safi_t safi, @@ -489,8 +506,8 @@ extern void bgp_clear_route(struct peer *, afi_t, safi_t); extern void bgp_clear_route_all(struct peer *); extern void bgp_clear_adj_in(struct peer *, afi_t, safi_t); extern void bgp_clear_stale_route(struct peer *, afi_t, safi_t); -extern int bgp_outbound_policy_exists(struct peer *, struct bgp_filter *); -extern int bgp_inbound_policy_exists(struct peer *, struct bgp_filter *); +extern bool bgp_outbound_policy_exists(struct peer *, struct bgp_filter *); +extern bool bgp_inbound_policy_exists(struct peer *, struct bgp_filter *); extern struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi, safi_t safi, struct prefix *p, @@ -512,7 +529,7 @@ extern void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, extern int bgp_nlri_parse_ip(struct peer *, struct attr *, struct bgp_nlri *); -extern int bgp_maximum_prefix_overflow(struct peer *, afi_t, safi_t, int); +extern bool bgp_maximum_prefix_overflow(struct peer *, afi_t, safi_t, int); extern void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, const union g_addr *nexthop, ifindex_t ifindex, @@ -597,15 +614,15 @@ extern void route_vty_out_overlay(struct vty *vty, struct prefix *p, struct bgp_path_info *path, int display, json_object *json); -extern int subgroup_process_announce_selected(struct update_subgroup *subgrp, - struct bgp_path_info *selected, - struct bgp_node *rn, - uint32_t addpath_tx_id); +extern void subgroup_process_announce_selected(struct update_subgroup *subgrp, + struct bgp_path_info *selected, + struct bgp_node *rn, + uint32_t addpath_tx_id); -extern int subgroup_announce_check(struct bgp_node *rn, - struct bgp_path_info *pi, - struct update_subgroup *subgrp, - struct prefix *p, struct attr *attr); +extern bool subgroup_announce_check(struct bgp_node *rn, + struct bgp_path_info *pi, + struct update_subgroup *subgrp, + struct prefix *p, struct attr *attr); extern void bgp_peer_clear_node_queue_drain_immediate(struct peer *peer); extern void bgp_process_queues_drain_immediate(void); @@ -629,8 +646,8 @@ extern void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, struct bgp_path_info_pair *result, afi_t afi, safi_t safi); extern void bgp_zebra_clear_route_change_flags(struct bgp_node *rn); -extern int bgp_zebra_has_route_changed(struct bgp_node *rn, - struct bgp_path_info *selected); +extern bool bgp_zebra_has_route_changed(struct bgp_node *rn, + struct bgp_path_info *selected); extern void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp, struct bgp_node *rn, diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 52b5402737..029570df35 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -2830,6 +2830,57 @@ static const struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = { route_match_ipv6_next_hop_free }; +/* `match ip next-hop IP_ADDRESS' */ + +static enum route_map_cmd_result_t +route_match_ipv4_next_hop(void *rule, const struct prefix *prefix, + route_map_object_t type, void *object) +{ + struct in_addr *addr = rule; + struct bgp_path_info *path; + + if (type == RMAP_BGP) { + path = object; + + if (path->attr->nexthop.s_addr == addr->s_addr || + (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4 && + IPV4_ADDR_SAME(&path->attr->mp_nexthop_global_in, addr))) + return RMAP_MATCH; + + return RMAP_NOMATCH; + } + + return RMAP_NOMATCH; +} + +static void *route_match_ipv4_next_hop_compile(const char *arg) +{ + struct in_addr *address; + int ret; + + address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr)); + + ret = inet_pton(AF_INET, arg, address); + if (!ret) { + XFREE(MTYPE_ROUTE_MAP_COMPILED, address); + return NULL; + } + + return address; +} + +static void route_match_ipv4_next_hop_free(void *rule) +{ + XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); +} + +static const struct route_map_rule_cmd route_match_ipv4_next_hop_cmd = { + "ip next-hop address", + route_match_ipv4_next_hop, + route_match_ipv4_next_hop_compile, + route_match_ipv4_next_hop_free +}; + /* `match ipv6 address prefix-list PREFIX_LIST' */ static enum route_map_cmd_result_t @@ -5110,6 +5161,28 @@ DEFUN (no_match_ipv6_next_hop, RMAP_EVENT_MATCH_DELETED); } +DEFPY (match_ipv4_next_hop, + match_ipv4_next_hop_cmd, + "[no$no] match ip next-hop address [A.B.C.D]", + NO_STR + MATCH_STR + IP_STR + "Match IP next-hop address of route\n" + "IP address\n" + "IP address of next-hop\n") +{ + int idx_ipv4 = 4; + + if (no) + return bgp_route_match_delete(vty, "ip next-hop address", NULL, + RMAP_EVENT_MATCH_DELETED); + + if (argv[idx_ipv4]->arg) + return bgp_route_match_add(vty, "ip next-hop address", + argv[idx_ipv4]->arg, + RMAP_EVENT_MATCH_ADDED); + return CMD_SUCCESS; +} DEFUN (set_ipv6_nexthop_peer, set_ipv6_nexthop_peer_cmd, @@ -5563,6 +5636,7 @@ void bgp_route_map_init(void) route_map_install_match(&route_match_ipv6_address_cmd); route_map_install_match(&route_match_ipv6_next_hop_cmd); + route_map_install_match(&route_match_ipv4_next_hop_cmd); route_map_install_match(&route_match_ipv6_address_prefix_list_cmd); route_map_install_match(&route_match_ipv6_next_hop_type_cmd); route_map_install_set(&route_set_ipv6_nexthop_global_cmd); @@ -5572,6 +5646,7 @@ void bgp_route_map_init(void) install_element(RMAP_NODE, &match_ipv6_next_hop_cmd); install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd); + install_element(RMAP_NODE, &match_ipv4_next_hop_cmd); install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd); install_element(RMAP_NODE, &no_set_ipv6_nexthop_global_cmd); install_element(RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd); diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c index 2ca0c7b96d..ee1c49666b 100644 --- a/bgpd/bgp_rpki.c +++ b/bgpd/bgp_rpki.c @@ -94,6 +94,7 @@ enum return_values { SUCCESS = 0, ERROR = -1 }; struct rpki_for_each_record_arg { struct vty *vty; unsigned int *prefix_amount; + as_t as; }; static int start(void); @@ -273,6 +274,17 @@ static void print_record(const struct pfx_record *record, struct vty *vty) record->max_len, record->asn); } +static void print_record_by_asn(const struct pfx_record *record, void *data) +{ + struct rpki_for_each_record_arg *arg = data; + struct vty *vty = arg->vty; + + if (record->asn == arg->as) { + (*arg->prefix_amount)++; + print_record(record, vty); + } +} + static void print_record_cb(const struct pfx_record *record, void *data) { struct rpki_for_each_record_arg *arg = data; @@ -621,6 +633,36 @@ static struct rtr_mgr_group *get_connected_group(void) return rtr_mgr_get_first_group(rtr_config); } +static void print_prefix_table_by_asn(struct vty *vty, as_t as) +{ + unsigned int number_of_ipv4_prefixes = 0; + unsigned int number_of_ipv6_prefixes = 0; + struct rtr_mgr_group *group = get_connected_group(); + struct rpki_for_each_record_arg arg; + + arg.vty = vty; + arg.as = as; + + if (!group) { + vty_out(vty, "Cannot find a connected group.\n"); + return; + } + + struct pfx_table *pfx_table = group->sockets[0]->pfx_table; + + vty_out(vty, "RPKI/RTR prefix table\n"); + vty_out(vty, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS"); + + arg.prefix_amount = &number_of_ipv4_prefixes; + pfx_table_for_each_ipv4_record(pfx_table, print_record_by_asn, &arg); + + arg.prefix_amount = &number_of_ipv6_prefixes; + pfx_table_for_each_ipv6_record(pfx_table, print_record_by_asn, &arg); + + vty_out(vty, "Number of IPv4 Prefixes: %u\n", number_of_ipv4_prefixes); + vty_out(vty, "Number of IPv6 Prefixes: %u\n", number_of_ipv6_prefixes); +} + static void print_prefix_table(struct vty *vty) { struct rpki_for_each_record_arg arg; @@ -1190,6 +1232,21 @@ DEFUN (show_rpki_prefix_table, return CMD_SUCCESS; } +DEFPY(show_rpki_as_number, show_rpki_as_number_cmd, + "show rpki as-number (1-4294967295)$by_asn", + SHOW_STR RPKI_OUTPUT_STRING + "Lookup by ASN in prefix table\n" + "AS Number\n") +{ + if (!is_synchronized()) { + vty_out(vty, "No Connection to RPKI cache server.\n"); + return CMD_WARNING; + } + + print_prefix_table_by_asn(vty, by_asn); + return CMD_SUCCESS; +} + DEFPY (show_rpki_prefix, show_rpki_prefix_cmd, "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)$asn]", @@ -1523,6 +1580,7 @@ static void install_cli_commands(void) install_element(VIEW_NODE, &show_rpki_cache_connection_cmd); install_element(VIEW_NODE, &show_rpki_cache_server_cmd); install_element(VIEW_NODE, &show_rpki_prefix_cmd); + install_element(VIEW_NODE, &show_rpki_as_number_cmd); /* Install debug commands */ install_element(CONFIG_NODE, &debug_rpki_cmd); diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c index d507161052..5cf0b73984 100644 --- a/bgpd/bgp_snmp.c +++ b/bgpd/bgp_snmp.c @@ -858,7 +858,7 @@ static int bgpTrapEstablished(struct peer *peer) oid index[sizeof(oid) * IN_ADDR_SIZE]; /* Check if this peer just went to Established */ - if ((peer->last_major_event != OpenConfirm) || !(peer_established(peer))) + if ((peer->ostatus != OpenConfirm) || !(peer_established(peer))) return 0; ret = inet_aton(peer->host, &addr); diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c index 04181d38be..3d74128da4 100644 --- a/bgpd/bgp_table.c +++ b/bgpd/bgp_table.c @@ -187,7 +187,8 @@ bgp_route_next_until_maxlen(struct bgp_node *node, const struct bgp_node *limit, return NULL; } -void bgp_table_range_lookup(const struct bgp_table *table, struct prefix *p, +void bgp_table_range_lookup(const struct bgp_table *table, + const struct prefix *p, uint8_t maxlen, struct list *matches) { struct bgp_node *node = bgp_node_from_rnode(table->route_table->top); diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h index 69cca9eee4..7b468cc036 100644 --- a/bgpd/bgp_table.h +++ b/bgpd/bgp_table.h @@ -217,7 +217,7 @@ static inline struct bgp_node *bgp_route_next_until(struct bgp_node *node, * bgp_node_get */ static inline struct bgp_node *bgp_node_get(struct bgp_table *const table, - struct prefix *p) + const struct prefix *p) { return bgp_node_from_rnode(route_node_get(table->route_table, p)); } @@ -226,7 +226,7 @@ static inline struct bgp_node *bgp_node_get(struct bgp_table *const table, * bgp_node_lookup */ static inline struct bgp_node * -bgp_node_lookup(const struct bgp_table *const table, struct prefix *p) +bgp_node_lookup(const struct bgp_table *const table, const struct prefix *p) { return bgp_node_from_rnode(route_node_lookup(table->route_table, p)); } @@ -243,7 +243,7 @@ static inline struct bgp_node *bgp_lock_node(struct bgp_node *node) * bgp_node_match */ static inline struct bgp_node *bgp_node_match(const struct bgp_table *table, - struct prefix *p) + const struct prefix *p) { return bgp_node_from_rnode(route_node_match(table->route_table, p)); } @@ -277,7 +277,7 @@ static inline unsigned long bgp_table_count(const struct bgp_table *const table) * bgp_table_get_next */ static inline struct bgp_node *bgp_table_get_next(const struct bgp_table *table, - struct prefix *p) + const struct prefix *p) { return bgp_node_from_rnode(route_table_get_next(table->route_table, p)); } @@ -347,7 +347,8 @@ static inline uint64_t bgp_table_version(struct bgp_table *table) return table->version; } -void bgp_table_range_lookup(const struct bgp_table *table, struct prefix *p, +void bgp_table_range_lookup(const struct bgp_table *table, + const struct prefix *p, uint8_t maxlen, struct list *matches); diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c index 50824cd6dd..a29721988e 100644 --- a/bgpd/bgp_updgrp.c +++ b/bgpd/bgp_updgrp.c @@ -831,17 +831,17 @@ void update_subgroup_inherit_info(struct update_subgroup *to, * * Returns true if the subgroup was deleted. */ -static int update_subgroup_check_delete(struct update_subgroup *subgrp) +static bool update_subgroup_check_delete(struct update_subgroup *subgrp) { if (!subgrp) - return 0; + return false; if (!LIST_EMPTY(&(subgrp->peers))) - return 0; + return false; update_subgroup_delete(subgrp); - return 1; + return true; } /* @@ -982,7 +982,7 @@ static struct update_subgroup *update_subgroup_find(struct update_group *updgrp, * Returns true if this subgroup is in a state that allows it to be * merged into another subgroup. */ -static int update_subgroup_ready_for_merge(struct update_subgroup *subgrp) +static bool update_subgroup_ready_for_merge(struct update_subgroup *subgrp) { /* @@ -990,13 +990,13 @@ static int update_subgroup_ready_for_merge(struct update_subgroup *subgrp) * out to peers. */ if (!bpacket_queue_is_empty(SUBGRP_PKTQ(subgrp))) - return 0; + return false; /* * Not ready if there enqueued updates waiting to be encoded. */ if (!advertise_list_is_empty(subgrp)) - return 0; + return false; /* * Don't attempt to merge a subgroup that needs a refresh. For one, @@ -1004,9 +1004,9 @@ static int update_subgroup_ready_for_merge(struct update_subgroup *subgrp) * another group. */ if (update_subgroup_needs_refresh(subgrp)) - return 0; + return false; - return 1; + return true; } /* @@ -1095,13 +1095,13 @@ static void update_subgroup_merge(struct update_subgroup *subgrp, * Returns true if the subgroup has been merged. The subgroup pointer * should not be accessed in this case. */ -int update_subgroup_check_merge(struct update_subgroup *subgrp, - const char *reason) +bool update_subgroup_check_merge(struct update_subgroup *subgrp, + const char *reason) { struct update_subgroup *target; if (!update_subgroup_ready_for_merge(subgrp)) - return 0; + return false; /* * Look for a subgroup to merge into. @@ -1112,10 +1112,10 @@ int update_subgroup_check_merge(struct update_subgroup *subgrp, } if (!target) - return 0; + return false; update_subgroup_merge(subgrp, target, reason); - return 1; + return true; } /* @@ -1143,14 +1143,14 @@ static int update_subgroup_merge_check_thread_cb(struct thread *thread) * * Returns true if a merge check will be performed shortly. */ -int update_subgroup_trigger_merge_check(struct update_subgroup *subgrp, - int force) +bool update_subgroup_trigger_merge_check(struct update_subgroup *subgrp, + int force) { if (subgrp->t_merge_check) - return 1; + return true; if (!force && !update_subgroup_ready_for_merge(subgrp)) - return 0; + return false; subgrp->t_merge_check = NULL; thread_add_timer_msec(bm->master, update_subgroup_merge_check_thread_cb, @@ -1158,7 +1158,7 @@ int update_subgroup_trigger_merge_check(struct update_subgroup *subgrp, SUBGRP_INCR_STAT(subgrp, merge_checks_triggered); - return 1; + return true; } /* @@ -1212,8 +1212,8 @@ static int update_subgroup_copy_packets(struct update_subgroup *dest, return count; } -static int updgrp_prefix_list_update(struct update_group *updgrp, - const char *name) +static bool updgrp_prefix_list_update(struct update_group *updgrp, + const char *name) { struct peer *peer; struct bgp_filter *filter; @@ -1225,13 +1225,13 @@ static int updgrp_prefix_list_update(struct update_group *updgrp, && (strcmp(name, PREFIX_LIST_OUT_NAME(filter)) == 0)) { PREFIX_LIST_OUT(filter) = prefix_list_lookup( UPDGRP_AFI(updgrp), PREFIX_LIST_OUT_NAME(filter)); - return 1; + return true; } - return 0; + return false; } -static int updgrp_filter_list_update(struct update_group *updgrp, - const char *name) +static bool updgrp_filter_list_update(struct update_group *updgrp, + const char *name) { struct peer *peer; struct bgp_filter *filter; @@ -1243,13 +1243,13 @@ static int updgrp_filter_list_update(struct update_group *updgrp, && (strcmp(name, FILTER_LIST_OUT_NAME(filter)) == 0)) { FILTER_LIST_OUT(filter) = as_list_lookup(FILTER_LIST_OUT_NAME(filter)); - return 1; + return true; } - return 0; + return false; } -static int updgrp_distribute_list_update(struct update_group *updgrp, - const char *name) +static bool updgrp_distribute_list_update(struct update_group *updgrp, + const char *name) { struct peer *peer; struct bgp_filter *filter; @@ -1261,9 +1261,9 @@ static int updgrp_distribute_list_update(struct update_group *updgrp, && (strcmp(name, DISTRIBUTE_OUT_NAME(filter)) == 0)) { DISTRIBUTE_OUT(filter) = access_list_lookup( UPDGRP_AFI(updgrp), DISTRIBUTE_OUT_NAME(filter)); - return 1; + return true; } - return 0; + return false; } static int updgrp_route_map_update(struct update_group *updgrp, diff --git a/bgpd/bgp_updgrp.h b/bgpd/bgp_updgrp.h index fe654bb3e3..403ca139f6 100644 --- a/bgpd/bgp_updgrp.h +++ b/bgpd/bgp_updgrp.h @@ -373,9 +373,9 @@ extern void update_subgroup_remove_peer(struct update_subgroup *, struct peer_af *); extern struct bgp_table *update_subgroup_rib(struct update_subgroup *); extern void update_subgroup_split_peer(struct peer_af *, struct update_group *); -extern int update_subgroup_check_merge(struct update_subgroup *, const char *); -extern int update_subgroup_trigger_merge_check(struct update_subgroup *, - int force); +extern bool update_subgroup_check_merge(struct update_subgroup *, const char *); +extern bool update_subgroup_trigger_merge_check(struct update_subgroup *, + int force); extern void update_group_policy_update(struct bgp *bgp, bgp_policy_type_e ptype, const char *pname, int route_update, int start_event); @@ -404,13 +404,13 @@ extern struct bpacket *bpacket_queue_first(struct bpacket_queue *q); struct bpacket *bpacket_queue_last(struct bpacket_queue *q); unsigned int bpacket_queue_length(struct bpacket_queue *q); unsigned int bpacket_queue_hwm_length(struct bpacket_queue *q); -int bpacket_queue_is_full(struct bgp *bgp, struct bpacket_queue *q); +bool bpacket_queue_is_full(struct bgp *bgp, struct bpacket_queue *q); extern void bpacket_queue_advance_peer(struct peer_af *paf); extern void bpacket_queue_remove_peer(struct peer_af *paf); extern void bpacket_add_peer(struct bpacket *pkt, struct peer_af *paf); unsigned int bpacket_queue_virtual_length(struct peer_af *paf); extern void bpacket_queue_show_vty(struct bpacket_queue *q, struct vty *vty); -int subgroup_packets_to_build(struct update_subgroup *subgrp); +bool subgroup_packets_to_build(struct update_subgroup *subgrp); extern struct bpacket *subgroup_update_packet(struct update_subgroup *s); extern struct bpacket *subgroup_withdraw_packet(struct update_subgroup *s); extern struct stream *bpacket_reformat_for_peer(struct bpacket *pkt, diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c index 4dc9dfa39a..6553211b0f 100644 --- a/bgpd/bgp_updgrp_packet.c +++ b/bgpd/bgp_updgrp_packet.c @@ -226,11 +226,11 @@ unsigned int bpacket_queue_hwm_length(struct bpacket_queue *q) return q->hwm_count - 1; } -int bpacket_queue_is_full(struct bgp *bgp, struct bpacket_queue *q) +bool bpacket_queue_is_full(struct bgp *bgp, struct bpacket_queue *q) { if (q->curr_count >= bgp->default_subgroup_pkt_queue_max) - return 1; - return 0; + return true; + return false; } void bpacket_add_peer(struct bpacket *pkt, struct peer_af *paf) @@ -656,22 +656,22 @@ static void bpacket_attr_vec_arr_update(struct bpacket_attr_vec_arr *vecarr, /* * Return if there are packets to build for this subgroup. */ -int subgroup_packets_to_build(struct update_subgroup *subgrp) +bool subgroup_packets_to_build(struct update_subgroup *subgrp) { struct bgp_advertise *adv; if (!subgrp) - return 0; + return false; adv = bgp_adv_fifo_first(&subgrp->sync->withdraw); if (adv) - return 1; + return true; adv = bgp_adv_fifo_first(&subgrp->sync->update); if (adv) - return 1; + return true; - return 0; + return false; } /* Make BGP update packet. */ diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 8c751e4f19..3db9866a99 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -533,7 +533,7 @@ int bgp_vty_find_and_parse_afi_safi_bgp(struct vty *vty, return *idx; } -static int peer_address_self_check(struct bgp *bgp, union sockunion *su) +static bool peer_address_self_check(struct bgp *bgp, union sockunion *su) { struct interface *ifp = NULL; @@ -545,9 +545,9 @@ static int peer_address_self_check(struct bgp *bgp, union sockunion *su) bgp->vrf_id); if (ifp) - return 1; + return true; - return 0; + return false; } /* Utility function for looking up peer from VTY. */ @@ -14086,7 +14086,8 @@ static bool peergroup_filter_check(struct peer *peer, afi_t afi, safi_t safi, /* Return true if the addpath type is set for peer and different from * peer-group. */ -static int peergroup_af_addpath_check(struct peer *peer, afi_t afi, safi_t safi) +static bool peergroup_af_addpath_check(struct peer *peer, afi_t afi, + safi_t safi) { enum bgp_addpath_strat type, g_type; @@ -14097,15 +14098,15 @@ static int peergroup_af_addpath_check(struct peer *peer, afi_t afi, safi_t safi) g_type = peer->group->conf->addpath_type[afi][safi]; if (type != g_type) - return 1; + return true; else - return 0; + return false; } - return 1; + return true; } - return 0; + return false; } /* This is part of the address-family block (unicast only) */ diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index f3ab608492..1c0f3c99b7 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -66,19 +66,19 @@ struct zclient *zclient = NULL; /* Can we install into zebra? */ -static inline int bgp_install_info_to_zebra(struct bgp *bgp) +static inline bool bgp_install_info_to_zebra(struct bgp *bgp) { if (zclient->sock <= 0) - return 0; + return false; if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) { zlog_debug( "%s: No zebra instance to talk to, not installing information", __func__); - return 0; + return false; } - return 1; + return true; } int zclient_num_connects; @@ -928,8 +928,8 @@ bgp_path_info_to_ipv6_nexthop(struct bgp_path_info *path, ifindex_t *ifindex) return nexthop; } -static int bgp_table_map_apply(struct route_map *map, struct prefix *p, - struct bgp_path_info *path) +static bool bgp_table_map_apply(struct route_map *map, struct prefix *p, + struct bgp_path_info *path) { route_map_result_t ret; @@ -937,7 +937,7 @@ static int bgp_table_map_apply(struct route_map *map, struct prefix *p, bgp_attr_flush(path->attr); if (ret != RMAP_DENYMATCH) - return 1; + return true; if (bgp_debug_zebra(p)) { if (p->family == AF_INET) { @@ -965,7 +965,7 @@ static int bgp_table_map_apply(struct route_map *map, struct prefix *p, buf[1], sizeof(buf[1]))); } } - return 0; + return false; } static struct thread *bgp_tm_thread_connect; @@ -1058,12 +1058,10 @@ int bgp_zebra_get_table_range(uint32_t chunk_size, return 0; } -static int update_ipv4nh_for_route_install(int nh_othervrf, - struct bgp *nh_bgp, - struct in_addr *nexthop, - struct attr *attr, - bool is_evpn, - struct zapi_nexthop *api_nh) +static bool update_ipv4nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, + struct in_addr *nexthop, + struct attr *attr, bool is_evpn, + struct zapi_nexthop *api_nh) { api_nh->gate.ipv4 = *nexthop; api_nh->vrf_id = nh_bgp->vrf_id; @@ -1083,15 +1081,16 @@ static int update_ipv4nh_for_route_install(int nh_othervrf, } else api_nh->type = NEXTHOP_TYPE_IPV4; - return 1; + return true; } -static int -update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, - struct in6_addr *nexthop, - ifindex_t ifindex, struct bgp_path_info *pi, - struct bgp_path_info *best_pi, bool is_evpn, - struct zapi_nexthop *api_nh) +static bool update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, + struct in6_addr *nexthop, + ifindex_t ifindex, + struct bgp_path_info *pi, + struct bgp_path_info *best_pi, + bool is_evpn, + struct zapi_nexthop *api_nh) { struct attr *attr; @@ -1108,7 +1107,7 @@ update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, api_nh->ifindex = attr->nh_ifindex; } else if (IN6_IS_ADDR_LINKLOCAL(nexthop)) { if (ifindex == 0) - return 0; + return false; api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; api_nh->ifindex = ifindex; } else { @@ -1136,7 +1135,7 @@ update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, } if (ifindex == 0) - return 0; + return false; api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; api_nh->ifindex = ifindex; } else { @@ -1146,7 +1145,7 @@ update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, } api_nh->gate.ipv6 = *nexthop; - return 1; + return true; } void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, @@ -1660,11 +1659,11 @@ int bgp_redistribute_resend(struct bgp *bgp, afi_t afi, int type, } /* Redistribute with route-map specification. */ -int bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name, - struct route_map *route_map) +bool bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name, + struct route_map *route_map) { if (red->rmap.name && (strcmp(red->rmap.name, name) == 0)) - return 0; + return false; XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name); /* Decrement the count for existing routemap and @@ -1675,18 +1674,18 @@ int bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name, red->rmap.map = route_map; route_map_counter_increment(red->rmap.map); - return 1; + return true; } /* Redistribute with metric specification. */ -int bgp_redistribute_metric_set(struct bgp *bgp, struct bgp_redist *red, - afi_t afi, int type, uint32_t metric) +bool bgp_redistribute_metric_set(struct bgp *bgp, struct bgp_redist *red, + afi_t afi, int type, uint32_t metric) { struct bgp_node *rn; struct bgp_path_info *pi; if (red->redist_metric_flag && red->redist_metric == metric) - return 0; + return false; red->redist_metric_flag = 1; red->redist_metric = metric; @@ -1713,7 +1712,7 @@ int bgp_redistribute_metric_set(struct bgp *bgp, struct bgp_redist *red, } } - return 1; + return true; } /* Unset redistribution. */ diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h index 5a02e2fbf9..39c28c452c 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -53,10 +53,10 @@ extern struct bgp_redist *bgp_redist_add(struct bgp *, afi_t, uint8_t, extern int bgp_redistribute_set(struct bgp *, afi_t, int, unsigned short, bool changed); extern int bgp_redistribute_resend(struct bgp *, afi_t, int, unsigned short); -extern int bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name, - struct route_map *route_map); -extern int bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *, afi_t, - int, uint32_t); +extern bool bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name, + struct route_map *route_map); +extern bool bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *, + afi_t, int, uint32_t); extern int bgp_redistribute_unset(struct bgp *, afi_t, int, unsigned short); extern int bgp_redistribute_unreg(struct bgp *, afi_t, int, unsigned short); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 267d67e46e..9452770100 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -320,13 +320,12 @@ void bgp_router_id_zebra_bump(vrf_id_t vrf_id, const struct prefix *router_id) } } -int bgp_router_id_static_set(struct bgp *bgp, struct in_addr id) +void bgp_router_id_static_set(struct bgp *bgp, struct in_addr id) { bgp->router_id_static = id; bgp_router_id_set(bgp, id.s_addr != INADDR_ANY ? &id : &bgp->router_id_zebra, true /* is config */); - return 0; } /* BGP's cluster-id control. */ @@ -393,25 +392,21 @@ time_t bgp_clock(void) } /* BGP timer configuration. */ -int bgp_timers_set(struct bgp *bgp, uint32_t keepalive, uint32_t holdtime, - uint32_t connect_retry) +void bgp_timers_set(struct bgp *bgp, uint32_t keepalive, uint32_t holdtime, + uint32_t connect_retry) { bgp->default_keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3); bgp->default_holdtime = holdtime; bgp->default_connect_retry = connect_retry; - - return 0; } /* mostly for completeness - CLI uses its own defaults */ -int bgp_timers_unset(struct bgp *bgp) +void bgp_timers_unset(struct bgp *bgp) { bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE; bgp->default_holdtime = BGP_DEFAULT_HOLDTIME; bgp->default_connect_retry = BGP_DEFAULT_CONNECT_RETRY; - - return 0; } /* BGP confederation configuration. */ @@ -499,18 +494,18 @@ int bgp_confederation_id_unset(struct bgp *bgp) } /* Is an AS part of the confed or not? */ -int bgp_confederation_peers_check(struct bgp *bgp, as_t as) +bool bgp_confederation_peers_check(struct bgp *bgp, as_t as) { int i; if (!bgp) - return 0; + return false; for (i = 0; i < bgp->confed_peers_cnt; i++) if (bgp->confed_peers[i] == as) - return 1; + return true; - return 0; + return false; } /* Add an AS to the confederation set. */ @@ -1415,8 +1410,8 @@ static int bgp_peer_conf_if_to_su_update_v4(struct peer *peer, return 0; } -static int bgp_peer_conf_if_to_su_update_v6(struct peer *peer, - struct interface *ifp) +static bool bgp_peer_conf_if_to_su_update_v6(struct peer *peer, + struct interface *ifp) { struct nbr_connected *ifc_nbr; @@ -1430,10 +1425,10 @@ static int bgp_peer_conf_if_to_su_update_v6(struct peer *peer, peer->su.sin6.sin6_len = sizeof(struct sockaddr_in6); #endif peer->su.sin6.sin6_scope_id = ifp->ifindex; - return 1; + return true; } - return 0; + return false; } /* @@ -2084,18 +2079,18 @@ int peer_activate(struct peer *peer, afi_t afi, safi_t safi) return ret; } -static int non_peergroup_deactivate_af(struct peer *peer, afi_t afi, - safi_t safi) +static bool non_peergroup_deactivate_af(struct peer *peer, afi_t afi, + safi_t safi) { if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { flog_err(EC_BGP_PEER_GROUP, "%s was called for peer-group %s", __func__, peer->host); - return 1; + return true; } /* Nothing to do if we've already deactivated this peer */ if (!peer->afc[afi][safi]) - return 0; + return false; /* De-activate the address family configuration. */ peer->afc[afi][safi] = 0; @@ -2104,7 +2099,7 @@ static int non_peergroup_deactivate_af(struct peer *peer, afi_t afi, flog_err(EC_BGP_PEER_DELETE, "couldn't delete af structure for peer %s(%s, %s)", peer->host, afi2str(afi), safi2str(safi)); - return 1; + return true; } if (peer->status == Established) { @@ -2130,7 +2125,7 @@ static int non_peergroup_deactivate_af(struct peer *peer, afi_t afi, } } - return 0; + return false; } int peer_deactivate(struct peer *peer, afi_t afi, safi_t safi) @@ -2547,15 +2542,14 @@ int peer_group_remote_as(struct bgp *bgp, const char *group_name, as_t *as, return 0; } -int peer_notify_unconfig(struct peer *peer) +void peer_notify_unconfig(struct peer *peer) { if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) bgp_notify_send(peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_PEER_UNCONFIG); - return 0; } -int peer_group_notify_unconfig(struct peer_group *group) +void peer_group_notify_unconfig(struct peer_group *group) { struct peer *peer, *other; struct listnode *node, *nnode; @@ -2568,7 +2562,6 @@ int peer_group_notify_unconfig(struct peer_group *group) } else peer_notify_unconfig(peer); } - return 0; } int peer_group_delete(struct peer_group *group) @@ -3771,10 +3764,10 @@ static void peer_drop_dynamic_neighbor(struct peer *peer) } /* If peer is configured at least one address family return 1. */ -int peer_active(struct peer *peer) +bool peer_active(struct peer *peer) { if (BGP_PEER_SU_UNSPEC(peer)) - return 0; + return false; if (peer->afc[AFI_IP][SAFI_UNICAST] || peer->afc[AFI_IP][SAFI_MULTICAST] || peer->afc[AFI_IP][SAFI_LABELED_UNICAST] || peer->afc[AFI_IP][SAFI_MPLS_VPN] || peer->afc[AFI_IP][SAFI_ENCAP] @@ -3786,12 +3779,12 @@ int peer_active(struct peer *peer) || peer->afc[AFI_IP6][SAFI_ENCAP] || peer->afc[AFI_IP6][SAFI_FLOWSPEC] || peer->afc[AFI_L2VPN][SAFI_EVPN]) - return 1; - return 0; + return true; + return false; } /* If peer is negotiated at least one address family return 1. */ -int peer_active_nego(struct peer *peer) +bool peer_active_nego(struct peer *peer) { if (peer->afc_nego[AFI_IP][SAFI_UNICAST] || peer->afc_nego[AFI_IP][SAFI_MULTICAST] @@ -3806,8 +3799,8 @@ int peer_active_nego(struct peer *peer) || peer->afc_nego[AFI_IP6][SAFI_ENCAP] || peer->afc_nego[AFI_IP6][SAFI_FLOWSPEC] || peer->afc_nego[AFI_L2VPN][SAFI_EVPN]) - return 1; - return 0; + return true; + return false; } void peer_change_action(struct peer *peer, afi_t afi, safi_t safi, @@ -4308,18 +4301,16 @@ int peer_af_flag_unset(struct peer *peer, afi_t afi, safi_t safi, uint32_t flag) } -int peer_tx_shutdown_message_set(struct peer *peer, const char *msg) +void peer_tx_shutdown_message_set(struct peer *peer, const char *msg) { XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message); peer->tx_shutdown_message = msg ? XSTRDUP(MTYPE_PEER_TX_SHUTDOWN_MSG, msg) : NULL; - return 0; } -int peer_tx_shutdown_message_unset(struct peer *peer) +void peer_tx_shutdown_message_unset(struct peer *peer) { XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message); - return 0; } @@ -4426,20 +4417,16 @@ int peer_ebgp_multihop_unset(struct peer *peer) } /* Neighbor description. */ -int peer_description_set(struct peer *peer, const char *desc) +void peer_description_set(struct peer *peer, const char *desc) { XFREE(MTYPE_PEER_DESC, peer->desc); peer->desc = XSTRDUP(MTYPE_PEER_DESC, desc); - - return 0; } -int peer_description_unset(struct peer *peer) +void peer_description_unset(struct peer *peer) { XFREE(MTYPE_PEER_DESC, peer->desc); - - return 0; } /* Neighbor update-source. */ @@ -4789,16 +4776,14 @@ int peer_default_originate_unset(struct peer *peer, afi_t afi, safi_t safi) return 0; } -int peer_port_set(struct peer *peer, uint16_t port) +void peer_port_set(struct peer *peer, uint16_t port) { peer->port = port; - return 0; } -int peer_port_unset(struct peer *peer) +void peer_port_unset(struct peer *peer) { peer->port = BGP_PORT_DEFAULT; - return 0; } /* diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 769ac32653..2b67a39efd 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -838,6 +838,37 @@ struct bgp_peer_gr { bgp_peer_gr_action_ptr action_fun; }; +/* BGP finite state machine events. */ +enum bgp_fsm_events { + BGP_Start = 1, + BGP_Stop, + TCP_connection_open, + TCP_connection_closed, + TCP_connection_open_failed, + TCP_fatal_error, + ConnectRetry_timer_expired, + Hold_Timer_expired, + KeepAlive_timer_expired, + Receive_OPEN_message, + Receive_KEEPALIVE_message, + Receive_UPDATE_message, + Receive_NOTIFICATION_message, + Clearing_Completed, + BGP_EVENTS_MAX, +}; + +/* BGP finite state machine status. */ +enum bgp_fsm_status { + Idle = 1, + Connect, + Active, + OpenSent, + OpenConfirm, + Established, + Clearing, + Deleted, + BGP_STATUS_MAX, +}; /* BGP neighbor structure. */ struct peer { @@ -896,15 +927,15 @@ struct peer { struct peer *doppelganger; /* Status of the peer. */ - int status; - int ostatus; + enum bgp_fsm_status status; + enum bgp_fsm_status ostatus; /* FSM events, stored for debug purposes. * Note: uchar used for reduced memory usage. */ - unsigned char cur_event; - unsigned char last_event; - unsigned char last_major_event; + enum bgp_fsm_events cur_event; + enum bgp_fsm_events last_event; + enum bgp_fsm_events last_major_event; /* Peer index, used for dumping TABLE_DUMP_V2 format */ uint16_t table_dump_index; @@ -1550,34 +1581,6 @@ struct bgp_nlri { #define BGP_NOTIFY_CAPABILITY_INVALID_LENGTH 2 #define BGP_NOTIFY_CAPABILITY_MALFORMED_CODE 3 -/* BGP finite state machine status. */ -#define Idle 1 -#define Connect 2 -#define Active 3 -#define OpenSent 4 -#define OpenConfirm 5 -#define Established 6 -#define Clearing 7 -#define Deleted 8 -#define BGP_STATUS_MAX 9 - -/* BGP finite state machine events. */ -#define BGP_Start 1 -#define BGP_Stop 2 -#define TCP_connection_open 3 -#define TCP_connection_closed 4 -#define TCP_connection_open_failed 5 -#define TCP_fatal_error 6 -#define ConnectRetry_timer_expired 7 -#define Hold_Timer_expired 8 -#define KeepAlive_timer_expired 9 -#define Receive_OPEN_message 10 -#define Receive_KEEPALIVE_message 11 -#define Receive_UPDATE_message 12 -#define Receive_NOTIFICATION_message 13 -#define Clearing_Completed 14 -#define BGP_EVENTS_MAX 15 - /* BGP timers default value. */ #define BGP_INIT_START_TIMER 1 /* The following 3 are RFC defaults that are overridden in bgp_vty.c with @@ -1739,8 +1742,8 @@ extern struct peer *peer_unlock_with_caller(const char *, struct peer *); extern bgp_peer_sort_t peer_sort(struct peer *peer); extern bgp_peer_sort_t peer_sort_lookup(struct peer *peer); -extern int peer_active(struct peer *); -extern int peer_active_nego(struct peer *); +extern bool peer_active(struct peer *); +extern bool peer_active_nego(struct peer *); extern void bgp_recalculate_all_bestpaths(struct bgp *bgp); extern struct peer *peer_create(union sockunion *, const char *, struct bgp *, as_t, as_t, int, afi_t, safi_t, @@ -1774,21 +1777,21 @@ extern int bgp_handle_socket(struct bgp *bgp, struct vrf *vrf, vrf_id_t old_vrf_id, bool create); extern void bgp_router_id_zebra_bump(vrf_id_t, const struct prefix *); -extern int bgp_router_id_static_set(struct bgp *, struct in_addr); +extern void bgp_router_id_static_set(struct bgp *, struct in_addr); extern int bgp_cluster_id_set(struct bgp *, struct in_addr *); extern int bgp_cluster_id_unset(struct bgp *); extern int bgp_confederation_id_set(struct bgp *, as_t); extern int bgp_confederation_id_unset(struct bgp *); -extern int bgp_confederation_peers_check(struct bgp *, as_t); +extern bool bgp_confederation_peers_check(struct bgp *, as_t); extern int bgp_confederation_peers_add(struct bgp *, as_t); extern int bgp_confederation_peers_remove(struct bgp *, as_t); -extern int bgp_timers_set(struct bgp *, uint32_t keepalive, uint32_t holdtime, - uint32_t connect_retry); -extern int bgp_timers_unset(struct bgp *); +extern void bgp_timers_set(struct bgp *, uint32_t keepalive, uint32_t holdtime, + uint32_t connect_retry); +extern void bgp_timers_unset(struct bgp *); extern int bgp_default_local_preference_set(struct bgp *, uint32_t); extern int bgp_default_local_preference_unset(struct bgp *); @@ -1799,19 +1802,19 @@ extern int bgp_default_subgroup_pkt_queue_max_unset(struct bgp *bgp); extern int bgp_listen_limit_set(struct bgp *, int); extern int bgp_listen_limit_unset(struct bgp *); -extern int bgp_update_delay_active(struct bgp *); -extern int bgp_update_delay_configured(struct bgp *); +extern bool bgp_update_delay_active(struct bgp *); +extern bool bgp_update_delay_configured(struct bgp *); extern int bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi); extern void peer_as_change(struct peer *, as_t, int); extern int peer_remote_as(struct bgp *, union sockunion *, const char *, as_t *, int, afi_t, safi_t); extern int peer_group_remote_as(struct bgp *, const char *, as_t *, int); extern int peer_delete(struct peer *peer); -extern int peer_notify_unconfig(struct peer *peer); +extern void peer_notify_unconfig(struct peer *peer); extern int peer_group_delete(struct peer_group *); extern int peer_group_remote_as_delete(struct peer_group *); extern int peer_group_listen_range_add(struct peer_group *, struct prefix *); -extern int peer_group_notify_unconfig(struct peer_group *group); +extern void peer_group_notify_unconfig(struct peer_group *group); extern int peer_activate(struct peer *, afi_t, safi_t); extern int peer_deactivate(struct peer *, afi_t, safi_t); @@ -1836,8 +1839,8 @@ extern int peer_ebgp_multihop_set(struct peer *, int); extern int peer_ebgp_multihop_unset(struct peer *); extern int is_ebgp_multihop_configured(struct peer *peer); -extern int peer_description_set(struct peer *, const char *); -extern int peer_description_unset(struct peer *); +extern void peer_description_set(struct peer *, const char *); +extern void peer_description_unset(struct peer *); extern int peer_update_source_if_set(struct peer *, const char *); extern int peer_update_source_addr_set(struct peer *, const union sockunion *); @@ -1848,8 +1851,8 @@ extern int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi, struct route_map *route_map); extern int peer_default_originate_unset(struct peer *, afi_t, safi_t); -extern int peer_port_set(struct peer *, uint16_t); -extern int peer_port_unset(struct peer *); +extern void peer_port_set(struct peer *, uint16_t); +extern void peer_port_unset(struct peer *); extern int peer_weight_set(struct peer *, afi_t, safi_t, uint16_t); extern int peer_weight_unset(struct peer *, afi_t, safi_t); @@ -1906,8 +1909,8 @@ extern int peer_clear_soft(struct peer *, afi_t, safi_t, enum bgp_clear_type); extern int peer_ttl_security_hops_set(struct peer *, int); extern int peer_ttl_security_hops_unset(struct peer *); -extern int peer_tx_shutdown_message_set(struct peer *, const char *msg); -extern int peer_tx_shutdown_message_unset(struct peer *); +extern void peer_tx_shutdown_message_set(struct peer *, const char *msg); +extern void peer_tx_shutdown_message_unset(struct peer *); extern int bgp_route_map_update_timer(struct thread *thread); extern void bgp_route_map_terminate(void); diff --git a/configure.ac b/configure.ac index 0d56b60e72..41d1911c37 100755 --- a/configure.ac +++ b/configure.ac @@ -1122,16 +1122,6 @@ case "$host_os" in AC_DEFINE([OPEN_BSD], [1], [OpenBSD]) AC_DEFINE([KAME], [1], [KAME IPv6]) AC_DEFINE([BSD_V6_SYSCTL], [1], [BSD v6 sysctl to turn on and off forwarding]) - - if test "$enable_pimd" != "no"; then - case "$host_os" in - openbsd6.0) - ;; - openbsd[6-9]*) - AC_MSG_FAILURE([pimd cannot be enabled as PIM support has been removed from OpenBSD 6.1]) - ;; - esac - fi ;; *) AC_MSG_RESULT([BSD]) @@ -1791,6 +1781,42 @@ if test "$enable_rpki" = "yes"; then ) fi +dnl ------------------------------------ +dnl pimd is not supported on OpenBSD and MacOS +dnl ------------------------------------ +if test "$enable_pimd" != "no"; then +AC_MSG_CHECKING([for pimd OS support]) +case "$host_os" in + darwin*) + AC_MSG_RESULT([no]) + enable_pimd="no" + ;; + openbsd*) + AC_MSG_RESULT([no]) + enable_pimd="no" + ;; + *) + AC_MSG_RESULT([yes]) + ;; +esac +fi + +dnl ------------------------------------- +dnl VRRP is only supported on linux +dnl ------------------------------------- +if test "$enable_vrrpd" != "no"; then +AC_MSG_CHECKING([for VRRP OS support]) +case "$host_os" in + linux*) + AC_MSG_RESULT([yes]) + ;; + *) + AC_MSG_RESULT([no]) + enable_vrrpd="no" + ;; +esac +fi + dnl ------------------------------------------ dnl Check whether rtrlib was build with ssh support dnl ------------------------------------------ diff --git a/doc/developer/building-frr-for-archlinux.rst b/doc/developer/building-frr-for-archlinux.rst new file mode 100644 index 0000000000..7ede35ad9c --- /dev/null +++ b/doc/developer/building-frr-for-archlinux.rst @@ -0,0 +1,129 @@ +Arch Linux +================ + +Installing Dependencies +----------------------- + +.. code-block:: console + + sudo pacman -Syu + sudo pacman -S \ + git autoconf automake libtool make cmake pcre readline texinfo \ + pkg-config pam json-c bison flex python-pytest \ + c-ares python systemd python2-ipaddress python-sphinx \ + systemd-libs net-snmp perl libcap + +.. include:: building-libyang.rst + +Protobuf +^^^^^^^^ + +.. code-block:: console + + sudo pacman -S protobuf-c + +ZeroMQ +^^^^^^ + +.. code-block:: console + + sudo pacman -S zeromq + +Building & Installing FRR +------------------------- + +Add FRR user and groups +^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: console + + sudo groupadd -r -g 92 frr + sudo groupadd -r -g 85 frrvty + sudo useradd --system -g frr --home-dir /var/run/frr/ \ + -c "FRR suite" --shell /sbin/nologin frr + sudo usermod -a -G frrvty frr + +Compile +^^^^^^^ + +.. include:: include-compile.rst + +Install FRR configuration files +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: console + + sudo install -m 775 -o frr -g frr -d /var/log/frr + sudo install -m 775 -o frr -g frrvty -d /etc/frr + sudo install -m 640 -o frr -g frrvty tools/etc/frr/vtysh.conf /etc/frr/vtysh.conf + sudo install -m 640 -o frr -g frr tools/etc/frr/frr.conf /etc/frr/frr.conf + sudo install -m 640 -o frr -g frr tools/etc/frr/daemons.conf /etc/frr/daemons.conf + sudo install -m 640 -o frr -g frr tools/etc/frr/daemons /etc/frr/daemons + +Tweak sysctls +^^^^^^^^^^^^^ + +Some sysctls need to be changed in order to enable IPv4/IPv6 forwarding and +MPLS (if supported by your platform). If your platform does not support MPLS, +skip the MPLS related configuration in this section. + +Edit :file:`/etc/sysctl.conf`[*Create the file if it doesn't exist*] and +append the following values (ignore the other settings): + +:: + + # Enable packet forwarding for IPv4 + net.ipv4.ip_forward=1 + + # Enable packet forwarding for IPv6 + net.ipv6.conf.all.forwarding=1 + +Reboot or use ``sysctl -p`` to apply the same config to the running system. + +Add MPLS kernel modules +""""""""""""""""""""""" + +To +enable, add the following lines to :file:`/etc/modules-load.d/modules.conf`: + +:: + + # Load MPLS Kernel Modules + mpls_router + mpls_iptunnel + + +And load the kernel modules on the running system: + +.. code-block:: console + + sudo modprobe mpls-router mpls-iptunnel + +Enable MPLS Forwarding +"""""""""""""""""""""" + +Edit :file:`/etc/sysctl.conf` and the following lines. Make sure to add a line +equal to :file:`net.mpls.conf.eth0.input` for each interface used with MPLS. + +:: + + # Enable MPLS Label processing on all interfaces + net.mpls.conf.eth0.input=1 + net.mpls.conf.eth1.input=1 + net.mpls.conf.eth2.input=1 + net.mpls.platform_labels=100000 + +Install service files +^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: console + + sudo install -m 644 tools/frr.service /etc/systemd/system/frr.service + sudo systemctl enable frr + +Start FRR +^^^^^^^^^ + +.. code-block:: shell + + systemctl start frr diff --git a/doc/developer/building-frr-for-centos6.rst b/doc/developer/building-frr-for-centos6.rst index 04c6b922ce..b730a5ee32 100644 --- a/doc/developer/building-frr-for-centos6.rst +++ b/doc/developer/building-frr-for-centos6.rst @@ -116,7 +116,19 @@ Update rpm database & Install newer sphinx sudo yum update sudo yum install python27-sphinx -.. include:: building-libyang.rst +Install libyang and its dependencies: + +.. code-block:: shell + + sudo yum install pcre-devel doxygen cmake + git clone https://github.com/CESNET/libyang.git + cd libyang + git checkout 090926a89d59a3c4000719505d563aaf6ac60f2 + mkdir build ; cd build + cmake -DENABLE_LYD_PRIV=ON -DCMAKE_INSTALL_PREFIX:PATH=/usr -D CMAKE_BUILD_TYPE:String="Release" .. + make build-rpm + sudo yum install ./rpms/RPMS/x86_64/libyang-0.16.111-0.x86_64.rpm ./rpms/RPMS/x86_64/libyang-devel-0.16.111-0.x86_64.rpm + cd ../.. Get FRR, compile it and install it (from Git) --------------------------------------------- diff --git a/doc/developer/building.rst b/doc/developer/building.rst index 859f612313..ef55954ac2 100644 --- a/doc/developer/building.rst +++ b/doc/developer/building.rst @@ -26,3 +26,4 @@ Building FRR building-frr-for-ubuntu1404 building-frr-for-ubuntu1604 building-frr-for-ubuntu1804 + building-frr-for-archlinux diff --git a/doc/user/nhrpd.rst b/doc/user/nhrpd.rst index 95ef9cb7ee..8d3bea7c94 100644 --- a/doc/user/nhrpd.rst +++ b/doc/user/nhrpd.rst @@ -199,6 +199,31 @@ NHRP Events Configure the Unix path for the event socket. +.. _show-nhrp: + +Show NHRP +========== + +.. index:: show [ip|ipv6] nhrp cache [json] +.. clicmd:: show [ip|ipv6] nhrp cache [json] + + Dump the cache entries. + +.. index:: show [ip|ipv6] nhrp opennhrp [json] +.. clicmd:: show [ip|ipv6] nhrp opennhrp [json] + + Dump the cache entries with opennhrp format. + +.. index:: show [ip|ipv6] nhrp nhs [json] +.. clicmd:: show [ip|ipv6] nhrp nhs [json] + + Dump the hub context. + +.. index:: show dmvpn [json] +.. clicmd:: show dmvpn [json] + + Dump the security contexts. + Configuration Example ===================== diff --git a/doc/user/overview.rst b/doc/user/overview.rst index eca521c1e5..c9934d1c68 100644 --- a/doc/user/overview.rst +++ b/doc/user/overview.rst @@ -306,6 +306,10 @@ BGP :t:`The Resource Public Key Infrastructure (RPKI) to Router Protocol. R. Bush, R. Austein. January 2013.` - :rfc:`6811` :t:`BGP Prefix Origin Validation. P. Mohapatra, J. Scudder, D. Ward, R. Bush, R. Austein. January 2013.` +- :rfc:`7606` + :t:`Revised Error Handling for BGP UPDATE Messages. E. Chen, J. Scudder, P. Mohapatra, K. Patel. August 2015.` +- :rfc:`7607` + :t:`Codification of AS 0 Processing. W. Kumari, R. Bush, H. Schiller, K. Patel. August 2015.` - :rfc:`7611` :t:`BGP ACCEPT_OWN Community Attribute. J. Uttaro, P. Mohapatra, D. Smith, R. Raszuk, J. Scudder. August 2015.` - :rfc:`7999` diff --git a/doc/user/pim.rst b/doc/user/pim.rst index 36c8b44aa4..f480c6bdc4 100644 --- a/doc/user/pim.rst +++ b/doc/user/pim.rst @@ -66,6 +66,14 @@ Certain signals have special meanings to *pimd*. prefix of group ranges covered. This command is vrf aware, to configure for a vrf, enter the vrf submode. +.. index:: ip pim register-accept-list PLIST +.. clicmd:: ip pim register-accept-list PLIST + + When pim receives a register packet the source of the packet will be compared + to the prefix-list specified, PLIST, and if a permit is received normal + processing continues. If a deny is returned for the source address of the + register packet a register stop message is sent to the source. + .. index:: ip pim spt-switchover infinity-and-beyond .. clicmd:: ip pim spt-switchover infinity-and-beyond diff --git a/doc/user/routemap.rst b/doc/user/routemap.rst index 472e2c53ff..f557cbe022 100644 --- a/doc/user/routemap.rst +++ b/doc/user/routemap.rst @@ -151,10 +151,15 @@ Route Map Match Command Matches the specified `prefix-len`. This is a Zebra specific command. -.. index:: match ip next-hop IPV4_ADDR -.. clicmd:: match ip next-hop IPV4_ADDR +.. index:: match ip next-hop address IPV4_ADDR +.. clicmd:: match ip next-hop address IPV4_ADDR - Matches the specified `ipv4_addr`. + This is a BGP specific match command. Matches the specified `ipv4_addr`. + +.. index:: match ipv6 next-hop IPV6_ADDR +.. clicmd:: match ipv6 next-hop IPV6_ADDR + + This is a BGP specific match command. Matches the specified `ipv6_addr`. .. index:: match as-path AS_PATH .. clicmd:: match as-path AS_PATH diff --git a/doc/user/sharp.rst b/doc/user/sharp.rst index 111e9dc9e8..199685cdfb 100644 --- a/doc/user/sharp.rst +++ b/doc/user/sharp.rst @@ -86,3 +86,20 @@ keyword. At present, no sharp commands will be preserved in the config. Allow end user to dump associated data with the nexthop tracking that may have been turned on. + +.. index:: sharp lsp +.. clicmd:: sharp lsp (0-100000) nexthop-group NAME [prefix A.B.C.D/M TYPE [instance (0-255)]] + + Install an LSP using the specified in-label, with nexthops as + listed in nexthop-group ``NAME``. The LSP is installed as type + ZEBRA_LSP_SHARP. If ``prefix`` is specified, an existing route with + type ``TYPE`` (and optional ``instance`` id) will be updated to use + the LSP. + +.. index:: sharp remove lsp +.. clicmd:: sharp remove lsp (0-100000) nexthop-group NAME [prefix A.B.C.D/M TYPE [instance (0-255)]] + + Remove a SHARPD LSP that uses the specified in-label, where the + nexthops are specified in nexthop-group ``NAME``. If ``prefix`` is + specified, remove label bindings from the route of type ``TYPE`` + also. diff --git a/isisd/isis_bpf.c b/isisd/isis_bpf.c index e916a50883..19695e7ab4 100644 --- a/isisd/isis_bpf.c +++ b/isisd/isis_bpf.c @@ -73,7 +73,7 @@ static const uint8_t ALL_ISS[6] = {0x09, 0x00, 0x2B, 0x00, 0x00, 0x05}; static const uint8_t ALL_ESS[6] = {0x09, 0x00, 0x2B, 0x00, 0x00, 0x04}; #endif -static char sock_buff[8192]; +static char sock_buff[16384]; static int open_bpf_dev(struct isis_circuit *circuit) { diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c index 3144b3c28e..fc70a344c8 100644 --- a/isisd/isis_cli.c +++ b/isisd/isis_cli.c @@ -1398,8 +1398,8 @@ void cli_show_ip_isis_metric(struct vty *vty, struct lyd_node *dnode, if (strmatch(l1, l2)) vty_out(vty, " isis metric %s\n", l1); else { - vty_out(vty, " isis metric %s level-1\n", l1); - vty_out(vty, " isis metric %s level-2\n", l2); + vty_out(vty, " isis metric level-1 %s\n", l1); + vty_out(vty, " isis metric level-2 %s\n", l2); } } diff --git a/isisd/isis_dlpi.c b/isisd/isis_dlpi.c index ea16f4af7f..5c15d1d29d 100644 --- a/isisd/isis_dlpi.c +++ b/isisd/isis_dlpi.c @@ -62,7 +62,7 @@ static const uint8_t ALL_ISS[6] = {0x09, 0x00, 0x2B, 0x00, 0x00, 0x05}; static const uint8_t ALL_ESS[6] = {0x09, 0x00, 0x2B, 0x00, 0x00, 0x04}; #endif -static uint8_t sock_buff[8192]; +static uint8_t sock_buff[16384]; static unsigned short pf_filter[] = { ENF_PUSHWORD + 0, /* Get the SSAP/DSAP values */ diff --git a/lib/agg_table.h b/lib/agg_table.h index 40ffe8c755..f95fed6758 100644 --- a/lib/agg_table.h +++ b/lib/agg_table.h @@ -86,13 +86,13 @@ static inline struct agg_node *agg_route_next(struct agg_node *node) } static inline struct agg_node *agg_node_get(struct agg_table *table, - struct prefix *p) + const struct prefix *p) { return agg_node_from_rnode(route_node_get(table->route_table, p)); } static inline struct agg_node * -agg_node_lookup(const struct agg_table *const table, struct prefix *p) +agg_node_lookup(const struct agg_table *const table, const struct prefix *p) { return agg_node_from_rnode(route_node_lookup(table->route_table, p)); } @@ -109,7 +109,7 @@ static inline struct agg_node *agg_route_next_until(struct agg_node *node, } static inline struct agg_node *agg_node_match(struct agg_table *table, - struct prefix *p) + const struct prefix *p) { return agg_node_from_rnode(route_node_match(table->route_table, p)); } diff --git a/lib/lib_vty.c b/lib/lib_vty.c index 787da08e28..9c927ca4af 100644 --- a/lib/lib_vty.c +++ b/lib/lib_vty.c @@ -93,7 +93,7 @@ static int qmem_walker(void *arg, struct memgroup *mg, struct memtype *mt) #endif ); } else { - if (mt->n_alloc != 0) { + if (mt->n_max != 0) { char size[32]; snprintf(size, sizeof(size), "%6zu", mt->size); #ifdef HAVE_MALLOC_USABLE_SIZE diff --git a/lib/libfrr.h b/lib/libfrr.h index f964c9e2a1..9d91ea9154 100644 --- a/lib/libfrr.h +++ b/lib/libfrr.h @@ -128,7 +128,8 @@ extern void frr_preinit(struct frr_daemon_info *daemon, int argc, char **argv); extern void frr_opt_add(const char *optstr, const struct option *longopts, const char *helpstr); extern int frr_getopt(int argc, char *const argv[], int *longindex); -extern void frr_help_exit(int status); + +extern __attribute__((__noreturn__)) void frr_help_exit(int status); extern struct thread_master *frr_init(void); extern const char *frr_get_progname(void); diff --git a/lib/memory.h b/lib/memory.h index 44ea19b557..e4e05faa4f 100644 --- a/lib/memory.h +++ b/lib/memory.h @@ -179,7 +179,8 @@ extern int qmem_walk(qmem_walk_fn *func, void *arg); extern int log_memstats(FILE *fp, const char *); #define log_memstats_stderr(prefix) log_memstats(stderr, prefix) -extern void memory_oom(size_t size, const char *name); +extern __attribute__((__noreturn__)) void memory_oom(size_t size, + const char *name); #ifdef __cplusplus } diff --git a/lib/mlag.c b/lib/mlag.c index 733dd41ea8..653fbe8fe9 100644 --- a/lib/mlag.c +++ b/lib/mlag.c @@ -85,9 +85,12 @@ int mlag_lib_decode_mlag_hdr(struct stream *s, struct mlag_msg *msg, size_t *length) { #define LIB_MLAG_HDR_LENGTH 8 + if (s == NULL || msg == NULL) + return -1; + *length = stream_get_endp(s); - if (s == NULL || msg == NULL || *length < LIB_MLAG_HDR_LENGTH) + if (*length < LIB_MLAG_HDR_LENGTH) return -1; *length -= LIB_MLAG_HDR_LENGTH; diff --git a/lib/ntop.c b/lib/ntop.c index 066e10e3e4..ccbf8793d3 100644 --- a/lib/ntop.c +++ b/lib/ntop.c @@ -165,7 +165,7 @@ inet4: return dst; } -#ifndef INET_NTOP_NO_OVERRIDE +#if !defined(INET_NTOP_NO_OVERRIDE) && !defined(__APPLE__) /* we want to override libc inet_ntop, but make sure it shows up in backtraces * as frr_inet_ntop (to avoid confusion while debugging) */ diff --git a/nhrpd/netlink_arp.c b/nhrpd/netlink_arp.c index 8fd8280c51..cf338a0876 100644 --- a/nhrpd/netlink_arp.c +++ b/nhrpd/netlink_arp.c @@ -65,11 +65,12 @@ static void netlink_neigh_msg(struct nlmsghdr *msg, struct zbuf *zb) struct nhrp_cache *c; struct interface *ifp; struct zbuf payload; - union sockunion addr; + union sockunion addr, lladdr; size_t len; - char buf[SU_ADDRSTRLEN]; + char buf[4][SU_ADDRSTRLEN]; int state; + memset(&lladdr, 0, sizeof(lladdr)); ndm = znl_pull(zb, sizeof(*ndm)); if (!ndm) return; @@ -82,6 +83,10 @@ static void netlink_neigh_msg(struct nlmsghdr *msg, struct zbuf *zb) sockunion_set(&addr, ndm->ndm_family, zbuf_pulln(&payload, len), len); break; + case NDA_LLADDR: + sockunion_set(&lladdr, ndm->ndm_family, + zbuf_pulln(&payload, len), len); + break; } } @@ -93,20 +98,34 @@ static void netlink_neigh_msg(struct nlmsghdr *msg, struct zbuf *zb) if (!c) return; - if (msg->nlmsg_type == RTM_GETNEIGH) { - debugf(NHRP_DEBUG_KERNEL, "Netlink: who-has %s dev %s", - sockunion2str(&addr, buf, sizeof(buf)), ifp->name); + debugf(NHRP_DEBUG_KERNEL, + "Netlink: %s %s dev %s lladdr %s nud 0x%x cache used %u type %u", + (msg->nlmsg_type == RTM_GETNEIGH) + ? "who-has" + : (msg->nlmsg_type == RTM_NEWNEIGH) ? "new-neigh" + : "del-neigh", + sockunion2str(&addr, buf[0], sizeof(buf[0])), ifp->name, + sockunion2str(&lladdr, buf[1], sizeof(buf[1])), ndm->ndm_state, + c->used, c->cur.type); + if (msg->nlmsg_type == RTM_GETNEIGH) { if (c->cur.type >= NHRP_CACHE_CACHED) { nhrp_cache_set_used(c, 1); - netlink_update_binding(ifp, &addr, - &c->cur.peer->vc->remote.nbma); + debugf(NHRP_DEBUG_KERNEL, + "Netlink: update binding for %s dev %s from c %s peer.vc.nbma %s to lladdr %s", + sockunion2str(&addr, buf[0], sizeof(buf[0])), + ifp->name, + sockunion2str(&c->cur.remote_nbma_natoa, buf[1], + sizeof(buf[1])), + sockunion2str(&c->cur.peer->vc->remote.nbma, + buf[2], sizeof(buf[2])), + sockunion2str(&lladdr, buf[3], sizeof(buf[3]))); + /* In case of shortcuts, nbma is given by lladdr, not + * vc->remote.nbma. + */ + netlink_update_binding(ifp, &addr, &lladdr); } } else { - debugf(NHRP_DEBUG_KERNEL, "Netlink: update %s dev %s nud %x", - sockunion2str(&addr, buf, sizeof(buf)), ifp->name, - ndm->ndm_state); - state = (msg->nlmsg_type == RTM_NEWNEIGH) ? ndm->ndm_state : NUD_FAILED; nhrp_cache_set_used(c, state == NUD_REACHABLE); diff --git a/nhrpd/nhrp_cache.c b/nhrpd/nhrp_cache.c index 81f7d99423..42f6a88f95 100644 --- a/nhrpd/nhrp_cache.c +++ b/nhrpd/nhrp_cache.c @@ -119,12 +119,43 @@ static void nhrp_cache_update_route(struct nhrp_cache *c) { struct prefix pfx; struct nhrp_peer *p = c->cur.peer; + char buf[3][SU_ADDRSTRLEN]; + struct nhrp_interface *nifp; sockunion2hostprefix(&c->remote_addr, &pfx); if (p && nhrp_peer_check(p, 1)) { - netlink_update_binding(p->ifp, &c->remote_addr, - &p->vc->remote.nbma); + if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) { + /* remote_nbma_natoa is already set. Therefore, binding + * should be updated to this value and not vc's remote + * nbma. + */ + debugf(NHRP_DEBUG_COMMON, + "cache (remote_nbma_natoa set): Update binding for %s dev %s from (deleted) peer.vc.nbma %s to %s", + sockunion2str(&c->remote_addr, buf[0], + sizeof(buf[0])), + p->ifp->name, + sockunion2str(&p->vc->remote.nbma, buf[1], + sizeof(buf[1])), + sockunion2str(&c->cur.remote_nbma_natoa, buf[2], + sizeof(buf[2]))); + + netlink_update_binding(p->ifp, &c->remote_addr, + &c->cur.remote_nbma_natoa); + } else { + /* update binding to peer->vc->remote->nbma */ + debugf(NHRP_DEBUG_COMMON, + "cache (remote_nbma_natoa unspec): Update binding for %s dev %s from (deleted) to peer.vc.nbma %s", + sockunion2str(&c->remote_addr, buf[0], + sizeof(buf[0])), + p->ifp->name, + sockunion2str(&p->vc->remote.nbma, buf[1], + sizeof(buf[1]))); + + netlink_update_binding(p->ifp, &c->remote_addr, + &p->vc->remote.nbma); + } + nhrp_route_announce(1, c->cur.type, &pfx, c->ifp, NULL, c->cur.mtu); if (c->cur.type >= NHRP_CACHE_DYNAMIC) { @@ -139,6 +170,17 @@ static void nhrp_cache_update_route(struct nhrp_cache *c) c->route_installed = 1; } } else { + /* debug the reason for peer check fail */ + if (p) { + nifp = p->ifp->info; + debugf(NHRP_DEBUG_COMMON, + "cache (peer check failed: online?%d requested?%d ipsec?%d)", + p->online, p->requested, + nifp->ipsec_profile ? 1 : 0); + } else + debugf(NHRP_DEBUG_COMMON, + "cache (peer check failed: no p)"); + if (c->nhrp_route_installed) { nhrp_route_update_nhrp(&pfx, NULL); c->nhrp_route_installed = 0; @@ -207,10 +249,10 @@ static void nhrp_cache_update_timers(struct nhrp_cache *c) static void nhrp_cache_authorize_binding(struct nhrp_reqid *r, void *arg) { struct nhrp_cache *c = container_of(r, struct nhrp_cache, eventid); - char buf[SU_ADDRSTRLEN]; + char buf[3][SU_ADDRSTRLEN]; debugf(NHRP_DEBUG_COMMON, "cache: %s %s: %s", c->ifp->name, - sockunion2str(&c->remote_addr, buf, sizeof(buf)), + sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0])), (const char *)arg); nhrp_reqid_free(&nhrp_event_reqid, r); @@ -230,6 +272,26 @@ static void nhrp_cache_authorize_binding(struct nhrp_reqid *r, void *arg) if (c->cur.peer) nhrp_peer_notify_add(c->cur.peer, &c->peer_notifier, nhrp_cache_peer_notifier); + + if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) { + debugf(NHRP_DEBUG_COMMON, + "cache: update binding for %s dev %s from (deleted) peer.vc.nbma %s to %s", + sockunion2str(&c->remote_addr, buf[0], + sizeof(buf[0])), + c->ifp->name, + (c->cur.peer ? sockunion2str( + &c->cur.peer->vc->remote.nbma, buf[1], + sizeof(buf[1])) + : "(no peer)"), + sockunion2str(&c->cur.remote_nbma_natoa, buf[2], + sizeof(buf[2]))); + + if (c->cur.peer) + netlink_update_binding( + c->cur.peer->ifp, &c->remote_addr, + &c->cur.remote_nbma_natoa); + } + nhrp_cache_update_route(c); notifier_call(&c->notifier_list, NOTIFY_CACHE_BINDING_CHANGE); } else { @@ -273,6 +335,8 @@ int nhrp_cache_update_binding(struct nhrp_cache *c, enum nhrp_cache_type type, int holding_time, struct nhrp_peer *p, uint32_t mtu, union sockunion *nbma_oa) { + char buf[2][SU_ADDRSTRLEN]; + if (c->cur.type > type || c->new.type > type) { nhrp_peer_unref(p); return 0; @@ -293,17 +357,31 @@ int nhrp_cache_update_binding(struct nhrp_cache *c, enum nhrp_cache_type type, break; } + sockunion2str(&c->cur.remote_nbma_natoa, buf[0], sizeof(buf[0])); + if (nbma_oa) + sockunion2str(nbma_oa, buf[1], sizeof(buf[1])); + nhrp_cache_reset_new(c); if (c->cur.type == type && c->cur.peer == p && c->cur.mtu == mtu) { + debugf(NHRP_DEBUG_COMMON, + "cache: same type %u, updating expiry and changing nbma addr from %s to %s", + type, buf[0], nbma_oa ? buf[1] : "(NULL)"); if (holding_time > 0) c->cur.expires = monotime(NULL) + holding_time; + if (nbma_oa) c->cur.remote_nbma_natoa = *nbma_oa; else memset(&c->cur.remote_nbma_natoa, 0, sizeof(c->cur.remote_nbma_natoa)); + nhrp_peer_unref(p); } else { + debugf(NHRP_DEBUG_COMMON, + "cache: new type %u/%u, or peer %s, or mtu %u/%u, nbma %s --> %s (map %d)", + c->cur.type, type, (c->cur.peer == p) ? "same" : "diff", + c->cur.mtu, mtu, buf[0], nbma_oa ? buf[1] : "(NULL)", + c->map); c->new.type = type; c->new.peer = p; c->new.mtu = mtu; diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c index 5ca477fb58..2dc019ce65 100644 --- a/nhrpd/nhrp_peer.c +++ b/nhrpd/nhrp_peer.c @@ -314,23 +314,29 @@ void nhrp_peer_send(struct nhrp_peer *p, struct zbuf *zb) zbuf_reset(zb); } -static void nhrp_handle_resolution_req(struct nhrp_packet_parser *p) +static void nhrp_handle_resolution_req(struct nhrp_packet_parser *pp) { + struct interface *ifp = pp->ifp; struct zbuf *zb, payload; struct nhrp_packet_header *hdr; struct nhrp_cie_header *cie; struct nhrp_extension_header *ext; - struct nhrp_interface *nifp; + struct nhrp_cache *c; + union sockunion cie_nbma, cie_proto, *proto_addr, *nbma_addr; + int holdtime, prefix_len, hostprefix_len; + struct nhrp_interface *nifp = ifp->info; struct nhrp_peer *peer; + size_t paylen; + char buf[SU_ADDRSTRLEN]; - if (!(p->if_ad->flags & NHRP_IFF_SHORTCUT)) { + if (!(pp->if_ad->flags & NHRP_IFF_SHORTCUT)) { debugf(NHRP_DEBUG_COMMON, "Shortcuts disabled"); /* FIXME: Send error indication? */ return; } - if (p->if_ad->network_id && p->route_type == NHRP_ROUTE_OFF_NBMA - && p->route_prefix.prefixlen < 8) { + if (pp->if_ad->network_id && pp->route_type == NHRP_ROUTE_OFF_NBMA + && pp->route_prefix.prefixlen < 8) { debugf(NHRP_DEBUG_COMMON, "Shortcut to more generic than /8 dropped"); return; @@ -338,45 +344,101 @@ static void nhrp_handle_resolution_req(struct nhrp_packet_parser *p) debugf(NHRP_DEBUG_COMMON, "Parsing and replying to Resolution Req"); - if (nhrp_route_address(p->ifp, &p->src_proto, NULL, &peer) + if (nhrp_route_address(ifp, &pp->src_proto, NULL, &peer) != NHRP_ROUTE_NBMA_NEXTHOP) return; -#if 0 - /* FIXME: Update requestors binding if CIE specifies holding time */ - nhrp_cache_update_binding( - NHRP_CACHE_CACHED, &p->src_proto, - nhrp_peer_get(p->ifp, &p->src_nbma), - htons(cie->holding_time)); -#endif + /* Copy payload CIE */ + hostprefix_len = 8 * sockunion_get_addrlen(&pp->if_ad->addr); + paylen = zbuf_used(&pp->payload); + debugf(NHRP_DEBUG_COMMON, "shortcut res_rep: paylen %zu", paylen); + + while ((cie = nhrp_cie_pull(&pp->payload, pp->hdr, &cie_nbma, + &cie_proto)) + != NULL) { + prefix_len = cie->prefix_length; + debugf(NHRP_DEBUG_COMMON, + "shortcut res_rep: parsing CIE with prefixlen=%u", + prefix_len); + if (prefix_len == 0 || prefix_len >= hostprefix_len) + prefix_len = hostprefix_len; + + if (prefix_len != hostprefix_len + && !(pp->hdr->flags + & htons(NHRP_FLAG_REGISTRATION_UNIQUE))) { + cie->code = NHRP_CODE_BINDING_NON_UNIQUE; + continue; + } + + /* We currently support only unique prefix registrations */ + if (prefix_len != hostprefix_len) { + cie->code = NHRP_CODE_ADMINISTRATIVELY_PROHIBITED; + continue; + } + + proto_addr = (sockunion_family(&cie_proto) == AF_UNSPEC) + ? &pp->src_proto + : &cie_proto; + nbma_addr = (sockunion_family(&cie_nbma) == AF_UNSPEC) + ? &pp->src_nbma + : &cie_nbma; + + holdtime = htons(cie->holding_time); + debugf(NHRP_DEBUG_COMMON, + "shortcut res_rep: holdtime is %u (if 0, using %u)", + holdtime, pp->if_ad->holdtime); + if (!holdtime) + holdtime = pp->if_ad->holdtime; + + c = nhrp_cache_get(ifp, proto_addr, 1); + if (!c) { + debugf(NHRP_DEBUG_COMMON, + "shortcut res_rep: no cache found"); + cie->code = NHRP_CODE_INSUFFICIENT_RESOURCES; + continue; + } + if (nbma_addr) + sockunion2str(nbma_addr, buf, sizeof(buf)); + + debugf(NHRP_DEBUG_COMMON, + "shortcut res_rep: updating binding for nmba addr %s", + nbma_addr ? buf : "(NULL)"); + if (!nhrp_cache_update_binding(c, NHRP_CACHE_DYNAMIC, holdtime, + nhrp_peer_ref(pp->peer), + htons(cie->mtu), nbma_addr)) { + cie->code = NHRP_CODE_ADMINISTRATIVELY_PROHIBITED; + continue; + } - nifp = peer->ifp->info; + cie->code = NHRP_CODE_SUCCESS; + } /* Create reply */ zb = zbuf_alloc(1500); - hdr = nhrp_packet_push(zb, NHRP_PACKET_RESOLUTION_REPLY, &p->src_nbma, - &p->src_proto, &p->dst_proto); + hdr = nhrp_packet_push(zb, NHRP_PACKET_RESOLUTION_REPLY, &pp->src_nbma, + &pp->src_proto, &pp->dst_proto); /* Copied information from request */ - hdr->flags = - p->hdr->flags & htons(NHRP_FLAG_RESOLUTION_SOURCE_IS_ROUTER - | NHRP_FLAG_RESOLUTION_SOURCE_STABLE); + hdr->flags = pp->hdr->flags + & htons(NHRP_FLAG_RESOLUTION_SOURCE_IS_ROUTER + | NHRP_FLAG_RESOLUTION_SOURCE_STABLE); hdr->flags |= htons(NHRP_FLAG_RESOLUTION_DESTINATION_STABLE | NHRP_FLAG_RESOLUTION_AUTHORATIVE); - hdr->u.request_id = p->hdr->u.request_id; + hdr->u.request_id = pp->hdr->u.request_id; - /* CIE payload */ + /* CIE payload for the reply packet */ cie = nhrp_cie_push(zb, NHRP_CODE_SUCCESS, &nifp->nbma, - &p->if_ad->addr); - cie->holding_time = htons(p->if_ad->holdtime); - cie->mtu = htons(p->if_ad->mtu); - if (p->if_ad->network_id && p->route_type == NHRP_ROUTE_OFF_NBMA) - cie->prefix_length = p->route_prefix.prefixlen; + &pp->if_ad->addr); + cie->holding_time = htons(pp->if_ad->holdtime); + cie->mtu = htons(pp->if_ad->mtu); + if (pp->if_ad->network_id && pp->route_type == NHRP_ROUTE_OFF_NBMA) + cie->prefix_length = pp->route_prefix.prefixlen; else - cie->prefix_length = 8 * sockunion_get_addrlen(&p->if_ad->addr); + cie->prefix_length = + 8 * sockunion_get_addrlen(&pp->if_ad->addr); /* Handle extensions */ - while ((ext = nhrp_ext_pull(&p->extensions, &payload)) != NULL) { + while ((ext = nhrp_ext_pull(&pp->extensions, &payload)) != NULL) { switch (htons(ext->type) & ~NHRP_EXTENSION_FLAG_COMPULSORY) { case NHRP_EXTENSION_NAT_ADDRESS: if (sockunion_family(&nifp->nat_nbma) == AF_UNSPEC) @@ -386,13 +448,13 @@ static void nhrp_handle_resolution_req(struct nhrp_packet_parser *p) if (!ext) goto err; cie = nhrp_cie_push(zb, NHRP_CODE_SUCCESS, - &nifp->nat_nbma, &p->if_ad->addr); + &nifp->nat_nbma, &pp->if_ad->addr); if (!cie) goto err; nhrp_ext_complete(zb, ext); break; default: - if (nhrp_ext_reply(zb, hdr, p->ifp, ext, &payload) < 0) + if (nhrp_ext_reply(zb, hdr, ifp, ext, &payload) < 0) goto err; break; } @@ -657,7 +719,7 @@ enum packet_type_t { PACKET_INDICATION, }; -static const struct { +static struct { enum packet_type_t type; const char *name; void (*handler)(struct nhrp_packet_parser *); @@ -897,11 +959,15 @@ void nhrp_peer_recv(struct nhrp_peer *p, struct zbuf *zb) if (extoff) { assert(zb->head > zb->buf); uint32_t header_offset = zb->head - zb->buf; - if ((extoff >= realsize) || (extoff < (header_offset))) { - info = "extoff larger than packet, or smaller than header"; + if (extoff >= realsize) { + info = "extoff larger than packet"; + goto drop; + } + if (extoff < header_offset) { + info = "extoff smaller than header offset"; goto drop; } - paylen = extoff - (zb->head - zb->buf); + paylen = extoff - header_offset; } else { paylen = zbuf_used(zb); } diff --git a/nhrpd/nhrp_shortcut.c b/nhrpd/nhrp_shortcut.c index 2552f9fd10..1c2b2b28f2 100644 --- a/nhrpd/nhrp_shortcut.c +++ b/nhrpd/nhrp_shortcut.c @@ -53,14 +53,21 @@ static int nhrp_shortcut_do_expire(struct thread *t) static void nhrp_shortcut_cache_notify(struct notifier_block *n, unsigned long cmd) { + char buf[PREFIX_STRLEN]; + struct nhrp_shortcut *s = container_of(n, struct nhrp_shortcut, cache_notifier); switch (cmd) { case NOTIFY_CACHE_UP: if (!s->route_installed) { - nhrp_route_announce(1, s->type, s->p, NULL, - &s->cache->remote_addr, 0); + debugf(NHRP_DEBUG_ROUTE, + "Shortcut: route install %s nh (unspec) dev %s", + prefix2str(s->p, buf, sizeof(buf)), + s->cache->ifp->name); + + nhrp_route_announce(1, s->type, s->p, s->cache->ifp, + NULL, 0); s->route_installed = 1; } break; @@ -84,6 +91,8 @@ static void nhrp_shortcut_update_binding(struct nhrp_shortcut *s, enum nhrp_cache_type type, struct nhrp_cache *c, int holding_time) { + char buf[2][PREFIX_STRLEN]; + s->type = type; if (c != s->cache) { if (s->cache) { @@ -98,13 +107,29 @@ static void nhrp_shortcut_update_binding(struct nhrp_shortcut *s, /* Force renewal of Zebra announce on prefix * change */ s->route_installed = 0; + debugf(NHRP_DEBUG_ROUTE, + "Shortcut: forcing renewal of zebra announce on prefix change peer %s ht %u cur nbma %s dev %s", + sockunion2str(&s->cache->remote_addr, + buf[0], sizeof(buf[0])), + holding_time, + sockunion2str( + &s->cache->cur.remote_nbma_natoa, + buf[1], sizeof(buf[1])), + s->cache->ifp->name); nhrp_shortcut_cache_notify(&s->cache_notifier, NOTIFY_CACHE_UP); } } - if (!s->cache || !s->cache->route_installed) + if (!s->cache || !s->cache->route_installed) { + debugf(NHRP_DEBUG_ROUTE, + "Shortcut: notify cache down because cache?%s or ri?%s", + s->cache ? "yes" : "no", + s->cache ? (s->cache->route_installed ? "yes" + : "no") + : "n/a"); nhrp_shortcut_cache_notify(&s->cache_notifier, NOTIFY_CACHE_DOWN); + } } if (s->type == NHRP_CACHE_NEGATIVE && !s->route_installed) { nhrp_route_announce(1, s->type, s->p, NULL, NULL, 0); @@ -141,6 +166,7 @@ static void nhrp_shortcut_delete(struct nhrp_shortcut *s) rn = route_node_lookup(shortcut_rib[afi], s->p); if (rn) { XFREE(MTYPE_NHRP_SHORTCUT, rn->info); + rn->info = NULL; route_unlock_node(rn); route_unlock_node(rn); } @@ -190,11 +216,10 @@ static void nhrp_shortcut_recv_resolution_rep(struct nhrp_reqid *reqid, struct nhrp_extension_header *ext; struct nhrp_cie_header *cie; struct nhrp_cache *c = NULL; - union sockunion *proto, cie_proto, *nbma, *nbma_natoa, cie_nbma, - nat_nbma; + union sockunion *proto, cie_proto, *nbma, cie_nbma, nat_nbma; struct prefix prefix, route_prefix; struct zbuf extpl; - char bufp[PREFIX_STRLEN], buf[3][SU_ADDRSTRLEN]; + char bufp[PREFIX_STRLEN], buf[4][SU_ADDRSTRLEN]; int holding_time = pp->if_ad->holdtime; nhrp_reqid_free(&nhrp_packet_reqid, &s->reqid); @@ -262,39 +287,55 @@ static void nhrp_shortcut_recv_resolution_rep(struct nhrp_reqid *reqid, } debugf(NHRP_DEBUG_COMMON, - "Shortcut: %s is at proto %s cie-nbma %s nat-nbma %s cie-holdtime %d", + "Shortcut: %s is at proto %s dst_proto %s cie-nbma %s nat-nbma %s cie-holdtime %d", prefix2str(&prefix, bufp, sizeof(bufp)), sockunion2str(proto, buf[0], sizeof(buf[0])), - sockunion2str(&cie_nbma, buf[1], sizeof(buf[1])), - sockunion2str(&nat_nbma, buf[2], sizeof(buf[2])), + sockunion2str(&pp->dst_proto, buf[1], sizeof(buf[1])), + sockunion2str(&cie_nbma, buf[2], sizeof(buf[2])), + sockunion2str(&nat_nbma, buf[3], sizeof(buf[3])), htons(cie->holding_time)); /* Update cache entry for the protocol to nbma binding */ - if (sockunion_family(&nat_nbma) != AF_UNSPEC) { + if (sockunion_family(&nat_nbma) != AF_UNSPEC) nbma = &nat_nbma; - nbma_natoa = &cie_nbma; - } else { + else nbma = &cie_nbma; - nbma_natoa = NULL; - } + if (sockunion_family(nbma)) { c = nhrp_cache_get(pp->ifp, proto, 1); if (c) { - nhrp_cache_update_binding(c, NHRP_CACHE_CACHED, + debugf(NHRP_DEBUG_COMMON, + "Shortcut: cache found, update binding"); + nhrp_cache_update_binding(c, NHRP_CACHE_DYNAMIC, holding_time, nhrp_peer_get(pp->ifp, nbma), - htons(cie->mtu), nbma_natoa); + htons(cie->mtu), nbma); + } else { + debugf(NHRP_DEBUG_COMMON, + "Shortcut: no cache for nbma %s", buf[2]); } } /* Update shortcut entry for subnet to protocol gw binding */ - if (c && !sockunion_same(proto, &pp->dst_proto)) { + if (c) { ps = nhrp_shortcut_get(&prefix); if (ps) { ps->addr = s->addr; - nhrp_shortcut_update_binding(ps, NHRP_CACHE_CACHED, c, + debugf(NHRP_DEBUG_COMMON, + "Shortcut: calling update_binding"); + nhrp_shortcut_update_binding(ps, NHRP_CACHE_DYNAMIC, c, holding_time); + } else { + debugf(NHRP_DEBUG_COMMON, + "Shortcut: proto diff but no ps"); } + } else { + debugf(NHRP_DEBUG_COMMON, + "NO Shortcut because c NULL?%s or same proto?%s", + c ? "no" : "yes", + proto && pp && sockunion_same(proto, &pp->dst_proto) + ? "yes" + : "no"); } debugf(NHRP_DEBUG_COMMON, "Shortcut: Resolution reply handled"); @@ -306,7 +347,9 @@ static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s) struct nhrp_packet_header *hdr; struct interface *ifp; struct nhrp_interface *nifp; + struct nhrp_afi_data *if_ad; struct nhrp_peer *peer; + struct nhrp_cie_header *cie; if (nhrp_route_address(NULL, &s->addr, NULL, &peer) != NHRP_ROUTE_NBMA_NEXTHOP) @@ -336,7 +379,15 @@ static void nhrp_shortcut_send_resolution_req(struct nhrp_shortcut *s) * - MTU: MTU of the source station * - Holding Time: Max time to cache the source information * */ - /* FIXME: Send holding time, and MTU */ + /* FIXME: push CIE for each local protocol address */ + cie = nhrp_cie_push(zb, NHRP_CODE_SUCCESS, NULL, NULL); + cie->prefix_length = 0xff; + if_ad = &nifp->afi[family2afi(sockunion_family(&s->addr))]; + cie->holding_time = htons(if_ad->holdtime); + cie->mtu = htons(if_ad->mtu); + debugf(NHRP_DEBUG_COMMON, + "Shortcut res_req: set cie ht to %u and mtu to %u. shortcut ht is %u", + ntohs(cie->holding_time), ntohs(cie->mtu), s->holding_time); nhrp_ext_request(zb, hdr, ifp); diff --git a/nhrpd/nhrp_vty.c b/nhrpd/nhrp_vty.c index f6d18fb77f..a3066f917e 100644 --- a/nhrpd/nhrp_vty.c +++ b/nhrpd/nhrp_vty.c @@ -12,6 +12,7 @@ #include "zclient.h" #include "stream.h" #include "filter.h" +#include "json.h" #include "nhrpd.h" #include "netlink.h" @@ -594,6 +595,7 @@ struct info_ctx { struct vty *vty; afi_t afi; int count; + struct json_object *json; }; static void show_ip_nhrp_cache(struct nhrp_cache *c, void *pctx) @@ -601,22 +603,60 @@ static void show_ip_nhrp_cache(struct nhrp_cache *c, void *pctx) struct info_ctx *ctx = pctx; struct vty *vty = ctx->vty; char buf[2][SU_ADDRSTRLEN]; + struct json_object *json = NULL; if (ctx->afi != family2afi(sockunion_family(&c->remote_addr))) return; - if (!ctx->count) { + + if (!ctx->count && !ctx->json) { vty_out(vty, "%-8s %-8s %-24s %-24s %-6s %s\n", "Iface", "Type", "Protocol", "NBMA", "Flags", "Identity"); } ctx->count++; + sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0])); + if (c->cur.peer) + sockunion2str(&c->cur.peer->vc->remote.nbma, + buf[1], sizeof(buf[1])); + else + snprintf(buf[1], sizeof(buf[1]), "-"); + + if (json) { + json = json_object_new_object(); + json_object_string_add(json, "interface", c->ifp->name); + json_object_string_add(json, "type", + nhrp_cache_type_str[c->cur.type]); + json_object_string_add(json, "protocol", buf[0]); + json_object_string_add(json, "nbma", buf[1]); + + if (c->used) + json_object_boolean_true_add(json, "used"); + else + json_object_boolean_false_add(json, "used"); + + if (c->t_timeout) + json_object_boolean_true_add(json, "timeout"); + else + json_object_boolean_false_add(json, "timeout"); + + if (c->t_auth) + json_object_boolean_true_add(json, "auth"); + else + json_object_boolean_false_add(json, "auth"); + + if (c->cur.peer) + json_object_string_add(json, "identity", + c->cur.peer->vc->remote.id); + else + json_object_string_add(json, "identity", "-"); + + json_object_array_add(ctx->json, json); + return; + } vty_out(ctx->vty, "%-8s %-8s %-24s %-24s %c%c%c %s\n", c->ifp->name, nhrp_cache_type_str[c->cur.type], - sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0])), - c->cur.peer ? sockunion2str(&c->cur.peer->vc->remote.nbma, - buf[1], sizeof(buf[1])) - : "-", + buf[0], buf[1], c->used ? 'U' : ' ', c->t_timeout ? 'T' : ' ', c->t_auth ? 'A' : ' ', c->cur.peer ? c->cur.peer->vc->remote.id : "-"); @@ -628,19 +668,35 @@ static void show_ip_nhrp_nhs(struct nhrp_nhs *n, struct nhrp_registration *reg, struct info_ctx *ctx = pctx; struct vty *vty = ctx->vty; char buf[2][SU_ADDRSTRLEN]; + struct json_object *json = NULL; - if (!ctx->count) { + if (!ctx->count && !ctx->json) { vty_out(vty, "%-8s %-24s %-16s %-16s\n", "Iface", "FQDN", "NBMA", "Protocol"); } ctx->count++; + if (reg && reg->peer) + sockunion2str(®->peer->vc->remote.nbma, + buf[0], sizeof(buf[0])); + else + snprintf(buf[0], sizeof(buf[0]), "-"); + sockunion2str(reg ? ®->proto_addr : &n->proto_addr, buf[1], + sizeof(buf[1])); + + if (ctx->json) { + json = json_object_new_object(); + json_object_string_add(json, "interface", n->ifp->name); + json_object_string_add(json, "fqdn", n->nbma_fqdn); + json_object_string_add(json, "nbma", buf[0]); + json_object_string_add(json, "protocol", buf[1]); + + json_object_array_add(ctx->json, json); + return; + } + vty_out(vty, "%-8s %-24s %-16s %-16s\n", n->ifp->name, n->nbma_fqdn, - (reg && reg->peer) ? sockunion2str(®->peer->vc->remote.nbma, - buf[0], sizeof(buf[0])) - : "-", - sockunion2str(reg ? ®->proto_addr : &n->proto_addr, buf[1], - sizeof(buf[1]))); + buf[0], buf[1]); } static void show_ip_nhrp_shortcut(struct nhrp_shortcut *s, void *pctx) @@ -649,6 +705,7 @@ static void show_ip_nhrp_shortcut(struct nhrp_shortcut *s, void *pctx) struct nhrp_cache *c; struct vty *vty = ctx->vty; char buf1[PREFIX_STRLEN], buf2[SU_ADDRSTRLEN]; + struct json_object *json = NULL; if (!ctx->count) { vty_out(vty, "%-8s %-24s %-24s %s\n", "Type", "Prefix", "Via", @@ -657,20 +714,82 @@ static void show_ip_nhrp_shortcut(struct nhrp_shortcut *s, void *pctx) ctx->count++; c = s->cache; - vty_out(ctx->vty, "%-8s %-24s %-24s %s\n", nhrp_cache_type_str[s->type], - prefix2str(s->p, buf1, sizeof(buf1)), - c ? sockunion2str(&c->remote_addr, buf2, sizeof(buf2)) : "", + if (c) + sockunion2str(&c->remote_addr, buf2, sizeof(buf2)); + prefix2str(s->p, buf1, sizeof(buf1)); + + if (ctx->json) { + json = json_object_new_object(); + json_object_string_add(json, "type", + nhrp_cache_type_str[s->type]); + json_object_string_add(json, "prefix", buf1); + + if (c) + json_object_string_add(json, "via", buf2); + + if (c && c->cur.peer) + json_object_string_add(json, "identity", + c->cur.peer->vc->remote.id); + else + json_object_string_add(json, "identity", ""); + + json_object_array_add(ctx->json, json); + return; + } + + vty_out(ctx->vty, "%-8s %-24s %-24s %s\n", + nhrp_cache_type_str[s->type], + buf1, buf2, (c && c->cur.peer) ? c->cur.peer->vc->remote.id : ""); } static void show_ip_opennhrp_cache(struct nhrp_cache *c, void *pctx) { struct info_ctx *ctx = pctx; - char buf[SU_ADDRSTRLEN]; + char buf[3][SU_ADDRSTRLEN]; + struct json_object *json = NULL; + if (ctx->afi != family2afi(sockunion_family(&c->remote_addr))) return; + sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0])); + if (c->cur.peer) + sockunion2str(&c->cur.peer->vc->remote.nbma, buf[1], + sizeof(buf[1])); + if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) + sockunion2str(&c->cur.remote_nbma_natoa, buf[2], + sizeof(buf[2])); + if (ctx->json) { + json = json_object_new_object(); + json_object_string_add(json, "type", + nhrp_cache_type_str[c->cur.type]); + + if (c->cur.peer && c->cur.peer->online) + json_object_boolean_true_add(json, "up"); + else + json_object_boolean_false_add(json, "up"); + + if (c->used) + json_object_boolean_true_add(json, "used"); + else + json_object_boolean_false_add(json, "used"); + + json_object_string_add(json, "protocolAddress", buf[0]); + json_object_int_add(json, "protocolAddressSize", + 8 * family2addrsize(sockunion_family + (&c->remote_addr))); + + if (c->cur.peer) + json_object_string_add(json, "nbmaAddress", buf[1]); + + if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) + json_object_string_add(json, "nbmaNatOaAddress", + buf[2]); + + json_object_array_add(ctx->json, json); + return; + } vty_out(ctx->vty, "Type: %s\n" "Flags:%s%s\n" @@ -678,40 +797,45 @@ static void show_ip_opennhrp_cache(struct nhrp_cache *c, void *pctx) nhrp_cache_type_str[c->cur.type], (c->cur.peer && c->cur.peer->online) ? " up" : "", c->used ? " used" : "", - sockunion2str(&c->remote_addr, buf, sizeof(buf)), + buf[0], 8 * family2addrsize(sockunion_family(&c->remote_addr))); - if (c->cur.peer) { - vty_out(ctx->vty, "NBMA-Address: %s\n", - sockunion2str(&c->cur.peer->vc->remote.nbma, buf, - sizeof(buf))); - } + if (c->cur.peer) + vty_out(ctx->vty, "NBMA-Address: %s\n", buf[1]); - if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) { - vty_out(ctx->vty, "NBMA-NAT-OA-Address: %s\n", - sockunion2str(&c->cur.remote_nbma_natoa, buf, - sizeof(buf))); - } + if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) + vty_out(ctx->vty, "NBMA-NAT-OA-Address: %s\n", buf[2]); vty_out(ctx->vty, "\n\n"); } DEFUN(show_ip_nhrp, show_ip_nhrp_cmd, - "show " AFI_CMD " nhrp [cache|nhs|shortcut|opennhrp]", + "show " AFI_CMD " nhrp [cache|nhs|shortcut|opennhrp] [json]", SHOW_STR AFI_STR "NHRP information\n" "Forwarding cache information\n" "Next hop server information\n" "Shortcut information\n" - "opennhrpctl style cache dump\n") + "opennhrpctl style cache dump\n" + JSON_STR) { struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); struct interface *ifp; struct info_ctx ctx = { - .vty = vty, .afi = cmd_to_afi(argv[1]), + .vty = vty, .afi = cmd_to_afi(argv[1]), .json = NULL }; - + bool uj = use_json(argc, argv); + struct json_object *json_path = NULL; + struct json_object *json_vrf = NULL, *json_vrf_path = NULL; + int ret = CMD_SUCCESS; + + if (uj) { + json_vrf = json_object_new_object(); + json_vrf_path = json_object_new_object(); + json_path = json_object_new_array(); + ctx.json = json_path; + } if (argc <= 3 || argv[3]->text[0] == 'c') { FOR_ALL_INTERFACES (vrf, ifp) nhrp_cache_foreach(ifp, show_ip_nhrp_cache, &ctx); @@ -721,49 +845,104 @@ DEFUN(show_ip_nhrp, show_ip_nhrp_cmd, } else if (argv[3]->text[0] == 's') { nhrp_shortcut_foreach(ctx.afi, show_ip_nhrp_shortcut, &ctx); } else { - vty_out(vty, "Status: ok\n\n"); + if (!ctx.json) + vty_out(vty, "Status: ok\n\n"); + else + json_object_string_add(json_vrf, "status", "ok"); + ctx.count++; FOR_ALL_INTERFACES (vrf, ifp) nhrp_cache_foreach(ifp, show_ip_opennhrp_cache, &ctx); } + if (uj) + json_object_int_add(json_vrf, "entriesCount", ctx.count); if (!ctx.count) { - vty_out(vty, "%% No entries\n"); - return CMD_WARNING; + if (!ctx.json) + vty_out(vty, "%% No entries\n"); + ret = CMD_WARNING; } - - return CMD_SUCCESS; + if (uj) { + json_object_object_add(json_vrf_path, "attr", json_vrf); + json_object_object_add(json_vrf_path, "table", ctx.json); + vty_out(vty, "%s", + json_object_to_json_string_ext( + json_vrf_path, JSON_C_TO_STRING_PRETTY)); + json_object_free(json_vrf_path); + } + return ret; } +struct dmvpn_cfg { + struct vty *vty; + struct json_object *json; +}; + static void show_dmvpn_entry(struct nhrp_vc *vc, void *ctx) { - struct vty *vty = ctx; + struct dmvpn_cfg *ctxt = ctx; + struct vty *vty; char buf[2][SU_ADDRSTRLEN]; + struct json_object *json = NULL; + + if (!ctxt || !ctxt->vty) + return; + vty = ctxt->vty; + sockunion2str(&vc->local.nbma, buf[0], sizeof(buf[0])); + sockunion2str(&vc->remote.nbma, buf[1], sizeof(buf[1])); + if (ctxt->json) { + json = json_object_new_object(); + json_object_string_add(json, "src", buf[0]); + json_object_string_add(json, "dst", buf[1]); + + if (notifier_active(&vc->notifier_list)) + json_object_boolean_true_add(json, "notifierActive"); + else + json_object_boolean_false_add(json, "notifierActive"); - vty_out(vty, "%-24s %-24s %c %-4d %-24s\n", - sockunion2str(&vc->local.nbma, buf[0], sizeof(buf[0])), - sockunion2str(&vc->remote.nbma, buf[1], sizeof(buf[1])), - notifier_active(&vc->notifier_list) ? 'n' : ' ', vc->ipsec, - vc->remote.id); + json_object_int_add(json, "sas", vc->ipsec); + json_object_string_add(json, "identity", vc->remote.id); + json_object_array_add(ctxt->json, json); + } else { + vty_out(vty, "%-24s %-24s %c %-4d %-24s\n", + buf[0], buf[1], notifier_active(&vc->notifier_list) ? + 'n' : ' ', vc->ipsec, vc->remote.id); + } } DEFUN(show_dmvpn, show_dmvpn_cmd, - "show dmvpn", + "show dmvpn [json]", SHOW_STR - "DMVPN information\n") + "DMVPN information\n" + JSON_STR) { - vty_out(vty, "%-24s %-24s %-6s %-4s %-24s\n", "Src", "Dst", "Flags", - "SAs", "Identity"); - - nhrp_vc_foreach(show_dmvpn_entry, vty); - + bool uj = use_json(argc, argv); + struct dmvpn_cfg ctxt; + struct json_object *json_path = NULL; + + ctxt.vty = vty; + if (!uj) { + ctxt.json = NULL; + vty_out(vty, "%-24s %-24s %-6s %-4s %-24s\n", + "Src", "Dst", "Flags", "SAs", "Identity"); + } else { + json_path = json_object_new_array(); + ctxt.json = json_path; + } + nhrp_vc_foreach(show_dmvpn_entry, &ctxt); + if (uj) { + vty_out(vty, "%s", + json_object_to_json_string_ext( + json_path, JSON_C_TO_STRING_PRETTY)); + json_object_free(json_path); + } return CMD_SUCCESS; } static void clear_nhrp_cache(struct nhrp_cache *c, void *data) { struct info_ctx *ctx = data; - if (c->cur.type <= NHRP_CACHE_CACHED) { + if (c->cur.type <= NHRP_CACHE_DYNAMIC) { nhrp_cache_update_binding(c, c->cur.type, -1, NULL, 0, NULL); ctx->count++; } diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index d87f02627b..0808f245e2 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -2335,7 +2335,7 @@ static struct stream *ospf_recv_packet(struct ospf *ospf, int fd, ip_len = iph->ip_len; -#if !defined(GNU_LINUX) && (OpenBSD < 200311) && (__FreeBSD_version < 1000000) +#if defined(__FreeBSD__) && (__FreeBSD_version < 1000000) /* * Kernel network code touches incoming IP header parameters, * before protocol specific processing. diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c index 7e24d924a4..8bfad8ee27 100644 --- a/pimd/pim_cmd.c +++ b/pimd/pim_cmd.c @@ -1520,6 +1520,10 @@ static void pim_show_interface_traffic(struct pim_instance *pim, pim_ifp->pim_ifstat_join_recv); json_object_int_add(json_row, "joinTx", pim_ifp->pim_ifstat_join_send); + json_object_int_add(json_row, "pruneTx", + pim_ifp->pim_ifstat_prune_send); + json_object_int_add(json_row, "pruneRx", + pim_ifp->pim_ifstat_prune_recv); json_object_int_add(json_row, "registerRx", pim_ifp->pim_ifstat_reg_recv); json_object_int_add(json_row, "registerTx", @@ -1706,7 +1710,10 @@ static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp, pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags)); if (PIM_IF_FLAG_TEST_S_G_RPT(ch->flags)) json_object_int_add(json_row, "SGRpt", 1); - + if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags)) + json_object_int_add(json_row, "protocolPim", 1); + if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags)) + json_object_int_add(json_row, "protocolIgmp", 1); json_object_object_get_ex(json_iface, ch_grp_str, &json_grp); if (!json_grp) { json_grp = json_object_new_object(); @@ -6625,18 +6632,18 @@ static int pim_cmd_spt_switchover(struct pim_instance *pim, switch (pim->spt.switchover) { case PIM_SPT_IMMEDIATE: - XFREE(MTYPE_PIM_SPT_PLIST_NAME, pim->spt.plist); + XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist); pim_upstream_add_lhr_star_pimreg(pim); break; case PIM_SPT_INFINITY: pim_upstream_remove_lhr_star_pimreg(pim, plist); - XFREE(MTYPE_PIM_SPT_PLIST_NAME, pim->spt.plist); + XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist); if (plist) pim->spt.plist = - XSTRDUP(MTYPE_PIM_SPT_PLIST_NAME, plist); + XSTRDUP(MTYPE_PIM_PLIST_NAME, plist); break; } @@ -6697,6 +6704,26 @@ DEFUN (no_ip_pim_spt_switchover_infinity_plist, return pim_cmd_spt_switchover(pim, PIM_SPT_IMMEDIATE, NULL); } +DEFPY (pim_register_accept_list, + pim_register_accept_list_cmd, + "[no] ip pim register-accept-list WORD$word", + NO_STR + IP_STR + PIM_STR + "Only accept registers from a specific source prefix list\n" + "Prefix-List name\n") +{ + PIM_DECLVAR_CONTEXT(vrf, pim); + + if (no) + XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist); + else { + XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist); + pim->register_plist = XSTRDUP(MTYPE_PIM_PLIST_NAME, word); + } + return CMD_SUCCESS; +} + DEFUN (ip_pim_joinprune_time, ip_pim_joinprune_time_cmd, "ip pim join-prune-interval (60-600)", @@ -10795,6 +10822,8 @@ void pim_cmd_init(void) install_element(CONFIG_NODE, &no_ip_pim_spt_switchover_infinity_plist_cmd); install_element(VRF_NODE, &no_ip_pim_spt_switchover_infinity_plist_cmd); + install_element(CONFIG_NODE, &pim_register_accept_list_cmd); + install_element(VRF_NODE, &pim_register_accept_list_cmd); install_element(CONFIG_NODE, &ip_pim_joinprune_time_cmd); install_element(VRF_NODE, &ip_pim_joinprune_time_cmd); install_element(CONFIG_NODE, &no_ip_pim_joinprune_time_cmd); diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 44d4ee7192..70e06ccc4e 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -628,6 +628,12 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, up->dualactive_ifchannel_count, up->flags); } + if (up_flags == PIM_UPSTREAM_FLAG_MASK_SRC_PIM) + PIM_IF_FLAG_SET_PROTO_PIM(ch->flags); + + if (up_flags == PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) + PIM_IF_FLAG_SET_PROTO_IGMP(ch->flags); + if (PIM_DEBUG_PIM_TRACE) zlog_debug("%s: ifchannel %s(%s) is created ", __func__, ch->sg_str, ch->interface->name); diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index 3d5cbd8ecf..425622b79e 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -69,7 +69,7 @@ struct pim_assert_metric { #define PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(flags) ((flags) &= ~PIM_IF_FLAG_MASK_ASSERT_TRACKING_DESIRED) /* - * Flat to tell us if the ifchannel is (S,G,rpt) + * Flag to tell us if the ifchannel is (S,G,rpt) */ #define PIM_IF_FLAG_MASK_S_G_RPT (1 << 2) #define PIM_IF_FLAG_TEST_S_G_RPT(flags) ((flags) & PIM_IF_FLAG_MASK_S_G_RPT) @@ -77,6 +77,23 @@ struct pim_assert_metric { #define PIM_IF_FLAG_UNSET_S_G_RPT(flags) ((flags) &= ~PIM_IF_FLAG_MASK_S_G_RPT) /* + * Flag to tell us if the ifchannel is proto PIM + */ +#define PIM_IF_FLAG_MASK_PROTO_PIM (1 << 3) +#define PIM_IF_FLAG_TEST_PROTO_PIM(flags) ((flags)&PIM_IF_FLAG_MASK_PROTO_PIM) +#define PIM_IF_FLAG_SET_PROTO_PIM(flags) ((flags) |= PIM_IF_FLAG_MASK_PROTO_PIM) +#define PIM_IF_FLAG_UNSET_PROTO_PIM(flags) \ + ((flags) &= ~PIM_IF_FLAG_MASK_PROTO_PIM) +/* + * Flag to tell us if the ifchannel is proto IGMP + */ +#define PIM_IF_FLAG_MASK_PROTO_IGMP (1 << 4) +#define PIM_IF_FLAG_TEST_PROTO_IGMP(flags) ((flags)&PIM_IF_FLAG_MASK_PROTO_IGMP) +#define PIM_IF_FLAG_SET_PROTO_IGMP(flags) \ + ((flags) |= PIM_IF_FLAG_MASK_PROTO_IGMP) +#define PIM_IF_FLAG_UNSET_PROTO_IGMP(flags) \ + ((flags) &= ~PIM_IF_FLAG_MASK_PROTO_IGMP) +/* Per-interface (S,G) state */ struct pim_ifchannel { diff --git a/pimd/pim_instance.c b/pimd/pim_instance.c index 347b0fc284..2cda628a90 100644 --- a/pimd/pim_instance.c +++ b/pimd/pim_instance.c @@ -69,6 +69,8 @@ static void pim_instance_terminate(struct pim_instance *pim) pim_msdp_exit(pim); + XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist); + XFREE(MTYPE_PIM_PLIST_NAME, pim->register_plist); XFREE(MTYPE_PIM_PIM_INSTANCE, pim); } diff --git a/pimd/pim_instance.h b/pimd/pim_instance.h index 7b1fd2e172..48dc2d9530 100644 --- a/pimd/pim_instance.h +++ b/pimd/pim_instance.h @@ -135,6 +135,9 @@ struct pim_instance { char *plist; } spt; + /* The name of the register-accept prefix-list */ + char *register_plist; + struct hash *rpf_hash; void *ssm_info; /* per-vrf SSM configuration */ diff --git a/pimd/pim_memory.c b/pimd/pim_memory.c index 2bbab67e45..6bc8062c4b 100644 --- a/pimd/pim_memory.c +++ b/pimd/pim_memory.c @@ -51,5 +51,5 @@ DEFINE_MTYPE(PIMD, PIM_JP_AGG_SOURCE, "PIM JP AGG Source") DEFINE_MTYPE(PIMD, PIM_PIM_INSTANCE, "PIM global state") DEFINE_MTYPE(PIMD, PIM_NEXTHOP_CACHE, "PIM nexthop cache state") DEFINE_MTYPE(PIMD, PIM_SSM_INFO, "PIM SSM configuration") -DEFINE_MTYPE(PIMD, PIM_SPT_PLIST_NAME, "PIM SPT Prefix List Name") +DEFINE_MTYPE(PIMD, PIM_PLIST_NAME, "PIM Prefix List Names") DEFINE_MTYPE(PIMD, PIM_VXLAN_SG, "PIM VxLAN mroute cache") diff --git a/pimd/pim_memory.h b/pimd/pim_memory.h index e5ca57a15d..6beeb60075 100644 --- a/pimd/pim_memory.h +++ b/pimd/pim_memory.h @@ -50,7 +50,7 @@ DECLARE_MTYPE(PIM_JP_AGG_SOURCE) DECLARE_MTYPE(PIM_PIM_INSTANCE) DECLARE_MTYPE(PIM_NEXTHOP_CACHE) DECLARE_MTYPE(PIM_SSM_INFO) -DECLARE_MTYPE(PIM_SPT_PLIST_NAME); +DECLARE_MTYPE(PIM_PLIST_NAME); DECLARE_MTYPE(PIM_VXLAN_SG) #endif /* _QUAGGA_PIM_MEMORY_H */ diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 5ce7863611..2e08ae28be 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -961,7 +961,7 @@ static inline void pim_mroute_copy(struct mfcctl *oil, static int pim_mroute_add(struct channel_oil *c_oil, const char *name) { struct pim_instance *pim = c_oil->pim; - struct mfcctl tmp_oil; + struct mfcctl tmp_oil = { {0} }; int err; pim->mroute_add_last = pim_time_monotonic_sec(); diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 19baecb9c2..7b0af89993 100644 --- a/pimd/pim_register.c +++ b/pimd/pim_register.c @@ -324,14 +324,13 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr, struct prefix_sg sg; uint32_t *bits; int i_am_rp = 0; - struct pim_interface *pim_ifp = NULL; - - pim_ifp = ifp->info; + struct pim_interface *pim_ifp = ifp->info; + struct pim_instance *pim = pim_ifp->pim; #define PIM_MSG_REGISTER_BIT_RESERVED_LEN 4 ip_hdr = (struct ip *)(tlv_buf + PIM_MSG_REGISTER_BIT_RESERVED_LEN); - if (!pim_rp_check_is_my_ip_address(pim_ifp->pim, dest_addr)) { + if (!pim_rp_check_is_my_ip_address(pim, dest_addr)) { if (PIM_DEBUG_PIM_REG) { char dest[INET_ADDRSTRLEN]; @@ -375,7 +374,7 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr, sg.src = ip_hdr->ip_src; sg.grp = ip_hdr->ip_dst; - i_am_rp = I_am_RP(pim_ifp->pim, sg.grp); + i_am_rp = I_am_RP(pim, sg.grp); if (PIM_DEBUG_PIM_REG) { char src_str[INET_ADDRSTRLEN]; @@ -387,9 +386,36 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr, if (i_am_rp && (dest_addr.s_addr - == ((RP(pim_ifp->pim, sg.grp))->rpf_addr.u.prefix4.s_addr))) { + == ((RP(pim, sg.grp))->rpf_addr.u.prefix4.s_addr))) { sentRegisterStop = 0; + if (pim->register_plist) { + struct prefix_list *plist; + struct prefix src; + + plist = prefix_list_lookup(AFI_IP, pim->register_plist); + + src.family = AF_INET; + src.prefixlen = IPV4_MAX_PREFIXLEN; + src.u.prefix4 = sg.src; + + if (prefix_list_apply(plist, &src) == PREFIX_DENY) { + pim_register_stop_send(ifp, &sg, dest_addr, + src_addr); + if (PIM_DEBUG_PIM_PACKETS) { + char src_str[INET_ADDRSTRLEN]; + + pim_inet4_dump("<src?>", src_addr, + src_str, + sizeof(src_str)); + zlog_debug("%s: Sending register-stop to %s for %pSG4 due to prefix-list denial, dropping packet", + __func__, src_str, &sg); + } + + return 0; + } + } + if (*bits & PIM_REGISTER_BORDER_BIT) { struct in_addr pimbr = pim_br_get_pmbr(&sg); if (PIM_DEBUG_PIM_PACKETS) @@ -411,14 +437,13 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr, } } - struct pim_upstream *upstream = - pim_upstream_find(pim_ifp->pim, &sg); + struct pim_upstream *upstream = pim_upstream_find(pim, &sg); /* * If we don't have a place to send ignore the packet */ if (!upstream) { upstream = pim_upstream_add( - pim_ifp->pim, &sg, ifp, + pim, &sg, ifp, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM, __func__, NULL); if (!upstream) { @@ -452,9 +477,8 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr, } if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) - || ((SwitchToSptDesiredOnRp(pim_ifp->pim, &sg)) - && pim_upstream_inherited_olist(pim_ifp->pim, upstream) - == 0)) { + || ((SwitchToSptDesiredOnRp(pim, &sg)) + && pim_upstream_inherited_olist(pim, upstream) == 0)) { pim_register_stop_send(ifp, &sg, dest_addr, src_addr); sentRegisterStop = 1; } else { @@ -463,15 +487,13 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr, upstream->sptbit); } if ((upstream->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) - || (SwitchToSptDesiredOnRp(pim_ifp->pim, &sg))) { + || (SwitchToSptDesiredOnRp(pim, &sg))) { if (sentRegisterStop) { pim_upstream_keep_alive_timer_start( - upstream, - pim_ifp->pim->rp_keep_alive_time); + upstream, pim->rp_keep_alive_time); } else { pim_upstream_keep_alive_timer_start( - upstream, - pim_ifp->pim->keep_alive_time); + upstream, pim->keep_alive_time); } } diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 355aa07048..a9f1d9335a 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -1294,10 +1294,16 @@ void pim_rp_show_information(struct pim_instance *pim, struct vty *vty, bool uj) json_row, "outboundInterface", rp_info->rp.source_nexthop .interface->name); - + else + json_object_string_add( + json_row, "outboundInterface", + "Unknown"); if (rp_info->i_am_rp) json_object_boolean_true_add(json_row, "iAmRP"); + else + json_object_boolean_false_add(json_row, + "iAmRP"); if (rp_info->plist) json_object_string_add(json_row, diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index efa58c1b1f..07f8315a19 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1794,10 +1794,16 @@ int pim_upstream_inherited_olist_decide(struct pim_instance *pim, continue; if (pim_upstream_evaluate_join_desired_interface(up, ch, starch)) { - int flag = PIM_OIF_FLAG_PROTO_PIM; + int flag = 0; if (!ch) flag = PIM_OIF_FLAG_PROTO_STAR; + else { + if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags)) + flag = PIM_OIF_FLAG_PROTO_IGMP; + if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags)) + flag |= PIM_OIF_FLAG_PROTO_PIM; + } pim_channel_add_oif(up->channel_oil, ifp, flag, __func__); diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c index 8a87dfbb55..72540903be 100644 --- a/pimd/pim_vty.c +++ b/pimd/pim_vty.c @@ -216,6 +216,11 @@ int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty) ssm->plist_name); ++writes; } + if (pim->register_plist) { + vty_out(vty, "%sip pim register-accept-list %s\n", spaces, + pim->register_plist); + ++writes; + } if (pim->spt.switchover == PIM_SPT_INFINITY) { if (pim->spt.plist) vty_out(vty, diff --git a/pimd/pim_vxlan.c b/pimd/pim_vxlan.c index 569b04d278..380c97a97c 100644 --- a/pimd/pim_vxlan.c +++ b/pimd/pim_vxlan.c @@ -253,8 +253,17 @@ static void pim_vxlan_orig_mr_up_del(struct pim_vxlan_sg *vxlan_sg) /* if there are other references register the source * for nht */ - if (up) - pim_rpf_update(vxlan_sg->pim, up, NULL, __func__); + if (up) { + enum pim_rpf_result r; + + r = pim_rpf_update(vxlan_sg->pim, up, NULL, __func__); + if (r == PIM_RPF_FAILURE) { + if (PIM_DEBUG_VXLAN) + zlog_debug( + "vxlan SG %s rpf_update failure", + vxlan_sg->sg_str); + } + } } } @@ -788,8 +797,8 @@ void pim_vxlan_sg_del(struct pim_instance *pim, struct prefix_sg *sg) if (!vxlan_sg) return; - pim_vxlan_sg_del_item(vxlan_sg); hash_release(pim->vxlan.sg_hash, vxlan_sg); + pim_vxlan_sg_del_item(vxlan_sg); } /******************************* MLAG handling *******************************/ diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index e791500ede..8355c2099d 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -835,7 +835,7 @@ void igmp_source_forward_stop(struct igmp_source *source) void pim_forward_start(struct pim_ifchannel *ch) { struct pim_upstream *up = ch->upstream; - uint32_t mask = PIM_OIF_FLAG_PROTO_PIM; + uint32_t mask = 0; if (PIM_DEBUG_PIM_TRACE) { char source_str[INET_ADDRSTRLEN]; @@ -853,9 +853,12 @@ void pim_forward_start(struct pim_ifchannel *ch) inet_ntoa(up->upstream_addr)); } - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) + if (PIM_IF_FLAG_TEST_PROTO_IGMP(ch->flags)) mask = PIM_OIF_FLAG_PROTO_IGMP; + if (PIM_IF_FLAG_TEST_PROTO_PIM(ch->flags)) + mask |= PIM_OIF_FLAG_PROTO_PIM; + pim_channel_add_oif(up->channel_oil, ch->interface, mask, __func__); } diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c index 486ccf6bfe..fd2e37e675 100644 --- a/sharpd/sharp_vty.c +++ b/sharpd/sharp_vty.c @@ -337,11 +337,129 @@ DEFUN_NOSH (show_debugging_sharpd, DEBUG_STR "Sharp Information\n") { - vty_out(vty, "Sharp debugging status\n"); + vty_out(vty, "Sharp debugging status:\n"); return CMD_SUCCESS; } +DEFPY(sharp_lsp_prefix_v4, sharp_lsp_prefix_v4_cmd, + "sharp lsp (0-100000)$inlabel\ + nexthop-group NHGNAME$nhgname\ + [prefix A.B.C.D/M$pfx\ + " FRR_IP_REDIST_STR_SHARPD "$type_str [instance (0-255)$instance]]", + "Sharp Routing Protocol\n" + "Add an LSP\n" + "The ingress label to use\n" + "Use nexthops from a nexthop-group\n" + "The nexthop-group name\n" + "Label a prefix\n" + "The v4 prefix to label\n" + FRR_IP_REDIST_HELP_STR_SHARPD + "Instance to use\n" + "Instance\n") +{ + struct nexthop_group_cmd *nhgc = NULL; + struct prefix p = {}; + int type = 0; + + /* We're offered a v4 prefix */ + if (pfx->family > 0 && type_str) { + p.family = pfx->family; + p.prefixlen = pfx->prefixlen; + p.u.prefix4 = pfx->prefix; + + type = proto_redistnum(AFI_IP, type_str); + if (type < 0) { + vty_out(vty, "%% Unknown route type '%s'\n", type_str); + return CMD_WARNING; + } + } else if (pfx->family > 0 || type_str) { + vty_out(vty, "%% Must supply both prefix and type\n"); + return CMD_WARNING; + } + + nhgc = nhgc_find(nhgname); + if (!nhgc) { + vty_out(vty, "%% Nexthop-group '%s' does not exist\n", + nhgname); + return CMD_WARNING; + } + + if (nhgc->nhg.nexthop == NULL) { + vty_out(vty, "%% Nexthop-group '%s' is empty\n", nhgname); + return CMD_WARNING; + } + + if (sharp_install_lsps_helper(true, pfx->family > 0 ? &p : NULL, + type, instance, inlabel, + &(nhgc->nhg)) == 0) + return CMD_SUCCESS; + else { + vty_out(vty, "%% LSP install failed!\n"); + return CMD_WARNING; + } +} + +DEFPY(sharp_remove_lsp_prefix_v4, sharp_remove_lsp_prefix_v4_cmd, + "sharp remove lsp \ + (0-100000)$inlabel\ + nexthop-group NHGNAME$nhgname\ + [prefix A.B.C.D/M$pfx\ + " FRR_IP_REDIST_STR_SHARPD "$type_str [instance (0-255)$instance]]", + "Sharp Routing Protocol\n" + "Remove data\n" + "Remove an LSP\n" + "The ingress label\n" + "Use nexthops from a nexthop-group\n" + "The nexthop-group name\n" + "Specify a v4 prefix\n" + "The v4 prefix to label\n" + FRR_IP_REDIST_HELP_STR_SHARPD + "Routing instance\n" + "Instance to use\n") +{ + struct nexthop_group_cmd *nhgc = NULL; + struct prefix p = {}; + int type = 0; + + /* We're offered a v4 prefix */ + if (pfx->family > 0 && type_str) { + p.family = pfx->family; + p.prefixlen = pfx->prefixlen; + p.u.prefix4 = pfx->prefix; + + type = proto_redistnum(AFI_IP, type_str); + if (type < 0) { + vty_out(vty, "%% Unknown route type '%s'\n", type_str); + return CMD_WARNING; + } + } else if (pfx->family > 0 || type_str) { + vty_out(vty, "%% Must supply both prefix and type\n"); + return CMD_WARNING; + } + + nhgc = nhgc_find(nhgname); + if (!nhgc) { + vty_out(vty, "%% Nexthop-group '%s' does not exist\n", + nhgname); + return CMD_WARNING; + } + + if (nhgc->nhg.nexthop == NULL) { + vty_out(vty, "%% Nexthop-group '%s' is empty\n", nhgname); + return CMD_WARNING; + } + + if (sharp_install_lsps_helper(false, pfx->family > 0 ? &p : NULL, + type, instance, inlabel, + &(nhgc->nhg)) == 0) + return CMD_SUCCESS; + else { + vty_out(vty, "%% LSP remove failed!\n"); + return CMD_WARNING; + } +} + void sharp_vty_init(void) { install_element(ENABLE_NODE, &install_routes_data_dump_cmd); @@ -351,6 +469,8 @@ void sharp_vty_init(void) install_element(ENABLE_NODE, &sharp_nht_data_dump_cmd); install_element(ENABLE_NODE, &watch_nexthop_v6_cmd); install_element(ENABLE_NODE, &watch_nexthop_v4_cmd); + install_element(ENABLE_NODE, &sharp_lsp_prefix_v4_cmd); + install_element(ENABLE_NODE, &sharp_remove_lsp_prefix_v4_cmd); install_element(VIEW_NODE, &show_debugging_sharpd_cmd); diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index 5baa74fe96..882e73f873 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -87,6 +87,61 @@ static int sharp_ifp_down(struct interface *ifp) return 0; } +int sharp_install_lsps_helper(bool install_p, const struct prefix *p, + uint8_t type, int instance, uint32_t in_label, + const struct nexthop_group *nhg) +{ + struct zapi_labels zl = {}; + struct zapi_nexthop *znh; + const struct nexthop *nh; + int i, ret; + + zl.type = ZEBRA_LSP_SHARP; + zl.local_label = in_label; + + if (p) { + SET_FLAG(zl.message, ZAPI_LABELS_FTN); + prefix_copy(&zl.route.prefix, p); + zl.route.type = type; + zl.route.instance = instance; + } + + i = 0; + for (ALL_NEXTHOPS_PTR(nhg, nh)) { + znh = &zl.nexthops[i]; + + /* Must have labels to be useful */ + if (nh->nh_label == NULL || nh->nh_label->num_labels == 0) + continue; + + if (nh->type == NEXTHOP_TYPE_IFINDEX || + nh->type == NEXTHOP_TYPE_BLACKHOLE) + /* Hmm - can't really deal with these types */ + continue; + + ret = zapi_nexthop_from_nexthop(znh, nh); + if (ret < 0) + return -1; + + i++; + } + + /* Whoops - no nexthops isn't very useful */ + if (i == 0) + return -1; + + zl.nexthop_num = i; + + if (install_p) + ret = zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_ADD, + &zl); + else + ret = zebra_send_mpls_labels(zclient, ZEBRA_MPLS_LABELS_DELETE, + &zl); + + return ret; +} + void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id, uint8_t instance, struct nexthop_group *nhg, uint32_t routes) @@ -241,43 +296,8 @@ void route_add(struct prefix *p, vrf_id_t vrf_id, for (ALL_NEXTHOPS_PTR(nhg, nh)) { api_nh = &api.nexthops[i]; - api_nh->vrf_id = nh->vrf_id; - api_nh->type = nh->type; - api_nh->weight = nh->weight; - - switch (nh->type) { - case NEXTHOP_TYPE_IPV4: - api_nh->gate = nh->gate; - break; - case NEXTHOP_TYPE_IPV4_IFINDEX: - api_nh->gate = nh->gate; - api_nh->ifindex = nh->ifindex; - break; - case NEXTHOP_TYPE_IFINDEX: - api_nh->ifindex = nh->ifindex; - break; - case NEXTHOP_TYPE_IPV6: - memcpy(&api_nh->gate.ipv6, &nh->gate.ipv6, 16); - break; - case NEXTHOP_TYPE_IPV6_IFINDEX: - api_nh->ifindex = nh->ifindex; - memcpy(&api_nh->gate.ipv6, &nh->gate.ipv6, 16); - break; - case NEXTHOP_TYPE_BLACKHOLE: - api_nh->bh_type = nh->bh_type; - break; - } - - if (nh->nh_label && nh->nh_label->num_labels > 0) { - int j; - - SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_LABEL); - - api_nh->label_num = nh->nh_label->num_labels; - for (j = 0; j < nh->nh_label->num_labels; j++) - api_nh->labels[j] = nh->nh_label->label[j]; - } + zapi_nexthop_from_nexthop(api_nh, nh); i++; } api.nexthop_num = i; diff --git a/sharpd/sharp_zebra.h b/sharpd/sharp_zebra.h index 57ffcc7690..c995d557af 100644 --- a/sharpd/sharp_zebra.h +++ b/sharpd/sharp_zebra.h @@ -37,4 +37,8 @@ extern void sharp_install_routes_helper(struct prefix *p, vrf_id_t vrf_id, uint32_t routes); extern void sharp_remove_routes_helper(struct prefix *p, vrf_id_t vrf_id, uint8_t instance, uint32_t routes); + +int sharp_install_lsps_helper(bool install_p, const struct prefix *p, + uint8_t type, int instance, uint32_t in_label, + const struct nexthop_group *nhg); #endif diff --git a/tests/bgpd/test_aspath.c b/tests/bgpd/test_aspath.c index 9feec7156a..b94355e8b8 100644 --- a/tests/bgpd/test_aspath.c +++ b/tests/bgpd/test_aspath.c @@ -474,6 +474,20 @@ static struct test_segment { 14, {NULL, NULL, 0, 0, 0, 0, 0, 0}, }, + { + /* 28 */ + "BGP_AS_ZERO", + "seq(8466,3,52737,0,4096)", + {0x2, 0x5, + 0x21, 0x12, + 0x00, 0x03, + 0xce, 0x01, + 0x00, 0x00, + 0x10, 0x00}, + 12, + {"8466 3 52737 0 4096", "8466 3 52737 0 4096", 5, 0, + NOT_ALL_PRIVATE, 4096, 4, 8466}, + }, {NULL, NULL, {0}, 0, {NULL, 0, 0}}}; #define COMMON_ATTRS \ @@ -678,6 +692,21 @@ static struct aspath_tests { COMMON_ATTR_SIZE + 3, &test_segments[0], }, + /* 13 */ + { + "4b AS4_PATH: BGP_AS_ZERO", + &test_segments[28], + "8466 3 52737 0 4096", + AS4_DATA, + -1, + PEER_CAP_AS4_RCV | PEER_CAP_AS4_ADV, + { + COMMON_ATTRS, + BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_AS4_PATH, 22, + }, + COMMON_ATTR_SIZE + 3, + }, {NULL, NULL, NULL, 0, 0, 0, {0}, 0}, }; diff --git a/tests/bgpd/test_aspath.py b/tests/bgpd/test_aspath.py index 15ae514c87..5fa1f11629 100644 --- a/tests/bgpd/test_aspath.py +++ b/tests/bgpd/test_aspath.py @@ -52,6 +52,7 @@ TestAspath.parsertest("redundantset2") TestAspath.parsertest("zero-size overflow") TestAspath.parsertest("zero-size overflow + valid segment") TestAspath.parsertest("invalid segment type") +TestAspath.parsertest("BGP_AS_ZERO") for i in range(10): TestAspath.okfail("prepend test %d" % i) @@ -77,3 +78,4 @@ TestAspath.attrtest("4b AS_PATH: too long2") TestAspath.attrtest("4b AS_PATH: bad flags") TestAspath.attrtest("4b AS4_PATH w/o AS_PATH") TestAspath.attrtest("4b AS4_PATH: confed") +TestAspath.attrtest("4b AS4_PATH: BGP_AS_ZERO") diff --git a/tests/bgpd/test_mp_attr.c b/tests/bgpd/test_mp_attr.c index c97ea57150..7fabaad7fa 100644 --- a/tests/bgpd/test_mp_attr.c +++ b/tests/bgpd/test_mp_attr.c @@ -951,12 +951,19 @@ static struct test_segment mp_prefix_sid[] = { "PREFIX-SID", "PREFIX-SID Test 1", { - 0x01, 0x00, 0x07, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, - 0x03, 0x00, 0x08, 0x00, - 0x00, 0x0a, 0x1b, 0xfe, - 0x00, 0x00, 0x0a + /* TLV[0] Latel-Index TLV */ + 0x01, /* Type 0x01:Label-Index */ + 0x00, 0x07, /* Length */ + 0x00, /* RESERVED */ + 0x00, 0x00, /* Flags */ + 0x00, 0x00, 0x00, 0x02, /* Label Index */ + + /* TLV[1] SRGB TLV */ + 0x03, /* Type 0x03:SRGB */ + 0x00, 0x08, /* Length */ + 0x00, 0x00, /* Flags */ + 0x0a, 0x1b, 0xfe, /* SRGB[0] first label */ + 0x00, 0x00, 0x0a /* SRBG[0] nb-labels in range */ }, .len = 21, .parses = SHOULD_PARSE, @@ -1027,7 +1034,7 @@ static void parse_test(struct peer *peer, struct test_segment *t, int type) parse_ret = bgp_mp_unreach_parse(&attr_args, &nlri); break; case BGP_ATTR_PREFIX_SID: - parse_ret = bgp_attr_prefix_sid(&attr_args, &nlri); + parse_ret = bgp_attr_prefix_sid(&attr_args); break; default: printf("unknown type"); diff --git a/tests/topotests/all-protocol-startup/test_all_protocol_startup.py b/tests/topotests/all-protocol-startup/test_all_protocol_startup.py index 16609221c1..a671e14e07 100755 --- a/tests/topotests/all-protocol-startup/test_all_protocol_startup.py +++ b/tests/topotests/all-protocol-startup/test_all_protocol_startup.py @@ -307,7 +307,7 @@ def test_converge_protocols(): expected = open(v4_routesFile).read().rstrip() expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) - actual = net['r%s' %i].cmd('vtysh -c "show ip route" | /usr/bin/tail -n +7 | sort 2> /dev/null').rstrip() + actual = net['r%s' %i].cmd('vtysh -c "show ip route" | /usr/bin/tail -n +7 | env LC_ALL=en_US.UTF-8 sort 2> /dev/null').rstrip() # Drop time in last update actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual) actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) @@ -329,7 +329,7 @@ def test_converge_protocols(): expected = open(v6_routesFile).read().rstrip() expected = ('\n'.join(expected.splitlines()) + '\n').splitlines(1) - actual = net['r%s' %i].cmd('vtysh -c "show ipv6 route" | /usr/bin/tail -n +7 | sort 2> /dev/null').rstrip() + actual = net['r%s' %i].cmd('vtysh -c "show ipv6 route" | /usr/bin/tail -n +7 | env LC_ALL=en_US.UTF-8 sort 2> /dev/null').rstrip() # Drop time in last update actual = re.sub(r" [0-2][0-9]:[0-5][0-9]:[0-5][0-9]", " XX:XX:XX", actual) actual = ('\n'.join(actual.splitlines()) + '\n').splitlines(1) diff --git a/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py b/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py index 59858d6fd3..e2bd80daa8 100755 --- a/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py +++ b/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py @@ -142,7 +142,7 @@ def test_bfd_connection(): test_func = partial(topotest.router_json_cmp, router, 'show bfd peers json', expected) - _, result = topotest.run_and_expect(test_func, None, count=8, wait=0.5) + _, result = topotest.run_and_expect(test_func, None, count=16, wait=0.5) assertmsg = '"{}" JSON output mismatches'.format(router.name) assert result is None, assertmsg @@ -173,7 +173,7 @@ def test_bfd_loss_intermediate(): test_func = partial(topotest.router_json_cmp, router, 'show bfd peers json', expected) - _, result = topotest.run_and_expect(test_func, None, count=8, wait=0.5) + _, result = topotest.run_and_expect(test_func, None, count=16, wait=0.5) assertmsg = '"{}" JSON output mismatches'.format(router.name) assert result is None, assertmsg @@ -229,7 +229,7 @@ def test_bfd_comes_back_again(): test_func = partial(topotest.router_json_cmp, router, 'show bfd peers json', expected) - _, result = topotest.run_and_expect(test_func, None, count=8, wait=0.5) + _, result = topotest.run_and_expect(test_func, None, count=16, wait=0.5) assertmsg = '"{}" JSON output mismatches'.format(router.name) assert result is None, assertmsg diff --git a/tests/topotests/bgp_prefix_sid/__init__.py b/tests/topotests/bgp_prefix_sid/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp_prefix_sid/__init__.py diff --git a/tests/topotests/bgp_prefix_sid/exabgp.env b/tests/topotests/bgp_prefix_sid/exabgp.env new file mode 100644 index 0000000000..6c554f5fa8 --- /dev/null +++ b/tests/topotests/bgp_prefix_sid/exabgp.env @@ -0,0 +1,53 @@ + +[exabgp.api] +encoder = text +highres = false +respawn = false +socket = '' + +[exabgp.bgp] +openwait = 60 + +[exabgp.cache] +attributes = true +nexthops = true + +[exabgp.daemon] +daemonize = true +pid = '/var/run/exabgp/exabgp.pid' +user = 'exabgp' + +[exabgp.log] +all = false +configuration = true +daemon = true +destination = '/var/log/exabgp.log' +enable = true +level = INFO +message = false +network = true +packets = false +parser = false +processes = true +reactor = true +rib = false +routes = false +short = false +timers = false + +[exabgp.pdb] +enable = false + +[exabgp.profile] +enable = false +file = '' + +[exabgp.reactor] +speed = 1.0 + +[exabgp.tcp] +acl = false +bind = '' +delay = 0 +once = false +port = 179 diff --git a/tests/topotests/bgp_prefix_sid/peer1/exabgp.cfg b/tests/topotests/bgp_prefix_sid/peer1/exabgp.cfg new file mode 100644 index 0000000000..5b55366a0e --- /dev/null +++ b/tests/topotests/bgp_prefix_sid/peer1/exabgp.cfg @@ -0,0 +1,103 @@ +group controller { + neighbor 10.0.0.1 { + router-id 10.0.0.101; + local-address 10.0.0.101; + local-as 2; + peer-as 1; + + family { + ipv4 nlri-mpls; + } + + static { + # ref: draft-ietf-idr-bgp-prefix-sid-27 + # + # IANA temporarily assigned the following: + # attribute code type (suggested value: 40) to + # the BGP Prefix-SID attribute + # + # 0 1 2 3 + # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + # | Type | Length | RESERVED | + # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + # | Flags | Label Index | + # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + # | Label Index | + # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + # Figure. Label-Index TLV (Prefix-SID type-1) + # + # 0 1 2 3 + # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + # | Type | Length | Flags | + # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + # | Flags | + # +-+-+-+-+-+-+-+-+ + # + # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + # | SRGB 1 (6 octets) | + # | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + # | | + # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + # + # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + # | SRGB n (6 octets) | + # | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + # | | + # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<Paste> + # Figure. Originator SRGB TLV (Prefix-SID type-3) + + # ExaBGP generic-attribute binary pattern: + # Attribute-type: 0x28 (40:BGP_PREFIX_SID) + # Attribute-flag: 0xc0 (Option, Transitive) + # Attribute-body: Label-Index TLV and Originator SRGB TLV + # Label-Index TLV: 0x01000700000000000001 + # Type (08bit): 0x01 + # Length (16bit): 0x0007 + # RESERVED (08bit): 0x00 + # Flags (16bit): 0x0000 + # Label Index (32bit): 0x00000001 + # Originator SRGB TLV: 0x03000800000c350000000a + # Type (08bit): 0x03 + # Length (16bit): 0x0008 (nb-SRGB is 1) + # Flags (16bit): 0x0000 + # SRGB1 (48bit): 0x0c3500:0x00000a (800000-800010 is SRGB1) + route 3.0.0.1/32 next-hop 10.0.0.101 label [800001] attribute [0x28 0xc0 0x0100070000000000000103000800000c350000000a]; + + # ExaBGP generic-attribute binary pattern: + # Attribute-type: 0x28 (40:BGP_PREFIX_SID) + # Attribute-flag: 0xc0 (Option, Transitive) + # Attribute-body: Label-Index TLV and Originator SRGB TLV + # Label-Index TLV: 0x01000700000000000001 + # Type (08bit): 0x01 + # Length (16bit): 0x0007 + # RESERVED (08bit): 0x00 + # Flags (16bit): 0x0000 + # Label Index (32bit): 0x00000002 + # Originator SRGB TLV: 0x03000800000c350000000a + # Type (08bit): 0x03 + # Length (16bit): 0x0008 (nb-SRGB is 1) + # Flags (16bit): 0x0000 + # SRGB1 (48bit): 0x0c3500:0x00000a (800000-800010 is SRGB1) + route 3.0.0.2/32 next-hop 10.0.0.101 label [800002] attribute [0x28 0xc0 0x0100070000000000000203000800000c350000000a]; + + # ExaBGP generic-attribute binary pattern: + # Attribute-type: 0x28 (40:BGP_PREFIX_SID) + # Attribute-flag: 0xc0 (Option, Transitive) + # Attribute-body: Label-Index TLV and Originator SRGB TLV + # Label-Index TLV: 0x01000700000000000001 + # Type (08bit): 0x01 + # Length (16bit): 0x0007 + # RESERVED (08bit): 0x00 + # Flags (16bit): 0x0000 + # Label Index (32bit): 0x00000003 + # Originator SRGB TLV: 0x03000800000c350000000a + # Type (08bit): 0x03 + # Length (16bit): 0x0008 (nb-SRGB is 1) + # Flags (16bit): 0x0000 + # SRGB1 (48bit): 0x0c3500:0x00000a (800000-800010 is SRGB1) + route 3.0.0.3/32 next-hop 10.0.0.101 label [800003] attribute [0x28 0xc0 0x0100070000000000000303000800000c350000000a]; + } + } +} diff --git a/tests/topotests/bgp_prefix_sid/peer2/exa-receive.py b/tests/topotests/bgp_prefix_sid/peer2/exa-receive.py new file mode 100755 index 0000000000..eaa6a67872 --- /dev/null +++ b/tests/topotests/bgp_prefix_sid/peer2/exa-receive.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +""" +exa-receive.py: Save received routes form ExaBGP into file +""" + +from sys import stdin,argv +from datetime import datetime + +# 1st arg is peer number +peer = int(argv[1]) + +# When the parent dies we are seeing continual newlines, so we only access so many before stopping +counter = 0 + +routesavefile = open('/tmp/peer%s-received.log' % peer, 'w') + +while True: + try: + line = stdin.readline() + routesavefile.write(line) + routesavefile.flush() + + if line == "": + counter += 1 + if counter > 100: + break + continue + + counter = 0 + except KeyboardInterrupt: + pass + except IOError: + # most likely a signal during readline + pass + +routesavefile.close() diff --git a/tests/topotests/bgp_prefix_sid/peer2/exabgp.cfg b/tests/topotests/bgp_prefix_sid/peer2/exabgp.cfg new file mode 100644 index 0000000000..dabd88e03d --- /dev/null +++ b/tests/topotests/bgp_prefix_sid/peer2/exabgp.cfg @@ -0,0 +1,19 @@ +group controller { + + process receive-routes { + run "/etc/exabgp/exa-receive.py 2"; + receive-routes; + encoder json; + } + + neighbor 10.0.0.1 { + router-id 10.0.0.102; + local-address 10.0.0.102; + local-as 3; + peer-as 1; + + family { + ipv4 nlri-mpls; + } + } +} diff --git a/tests/topotests/bgp_prefix_sid/r1/bgpd.conf b/tests/topotests/bgp_prefix_sid/r1/bgpd.conf new file mode 100644 index 0000000000..7a38cc307f --- /dev/null +++ b/tests/topotests/bgp_prefix_sid/r1/bgpd.conf @@ -0,0 +1,15 @@ +log stdout notifications +log monitor notifications +log commands +! +router bgp 1 + bgp router-id 10.0.0.1 + no bgp default ipv4-unicast + neighbor 10.0.0.101 remote-as 2 + neighbor 10.0.0.102 remote-as 3 + ! + address-family ipv4 labeled-unicast + neighbor 10.0.0.101 activate + neighbor 10.0.0.102 activate + exit-address-family +! diff --git a/tests/topotests/bgp_prefix_sid/r1/zebra.conf b/tests/topotests/bgp_prefix_sid/r1/zebra.conf new file mode 100644 index 0000000000..0cd26052f2 --- /dev/null +++ b/tests/topotests/bgp_prefix_sid/r1/zebra.conf @@ -0,0 +1,7 @@ +hostname r1 +! +interface r1-eth0 + ip address 10.0.0.1/24 + no shutdown +! +line vty diff --git a/tests/topotests/bgp_prefix_sid/test_bgp_prefix_sid.py b/tests/topotests/bgp_prefix_sid/test_bgp_prefix_sid.py new file mode 100755 index 0000000000..dc203cabc5 --- /dev/null +++ b/tests/topotests/bgp_prefix_sid/test_bgp_prefix_sid.py @@ -0,0 +1,173 @@ +#!/usr/bin/env python + +# +# test_bgp_prefix_sid.py +# Part of NetDEF Topology Tests +# +# Copyright (c) 2020 by LINE Corporation +# Copyright (c) 2020 by Hiroki Shirokura <slank.dev@gmail.com> +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +""" +test_bgp_prefix_sid.py: Test BGP topology with EBGP on prefix-sid +""" + +import json +import os +import sys +import functools +import pytest + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, '../')) + +# pylint: disable=C0413 +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger +from mininet.topo import Topo + + +class TemplateTopo(Topo): + def build(self, **_opts): + tgen = get_topogen(self) + router = tgen.add_router('r1') + switch = tgen.add_switch('s1') + switch.add_link(router) + + switch = tgen.gears['s1'] + peer1 = tgen.add_exabgp_peer('peer1', ip='10.0.0.101', defaultRoute='via 10.0.0.1') + peer2 = tgen.add_exabgp_peer('peer2', ip='10.0.0.102', defaultRoute='via 10.0.0.1') + switch.add_link(peer1) + switch.add_link(peer2) + + +def setup_module(module): + tgen = Topogen(TemplateTopo, module.__name__) + tgen.start_topology() + + router = tgen.gears['r1'] + router.load_config(TopoRouter.RD_ZEBRA, os.path.join(CWD, '{}/zebra.conf'.format('r1'))) + router.load_config(TopoRouter.RD_BGP, os.path.join(CWD, '{}/bgpd.conf'.format('r1'))) + router.start() + + logger.info('starting exaBGP on peer1') + peer_list = tgen.exabgp_peers() + for pname, peer in peer_list.iteritems(): + peer_dir = os.path.join(CWD, pname) + env_file = os.path.join(CWD, 'exabgp.env') + logger.info('Running ExaBGP peer') + peer.start(peer_dir, env_file) + logger.info(pname) + + +def teardown_module(module): + tgen = get_topogen() + tgen.stop_topology() + + +def test_r1_receive_and_advertise_prefix_sid_type1(): + tgen = get_topogen() + router = tgen.gears['r1'] + + def _check_type1_r1(router, prefix, remoteLabel, labelIndex): + output = router.vtysh_cmd('show bgp ipv4 labeled-unicast {} json'.format(prefix)) + output = json.loads(output) + expected = { + 'prefix': prefix, + 'advertisedTo': { '10.0.0.101':{}, '10.0.0.102':{} }, + 'paths': [{ + 'valid':True, + 'remoteLabel': remoteLabel, + 'labelIndex': labelIndex, + }] + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_check_type1_r1, router, '3.0.0.1/32', 800001, 1) + success, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5) + assert result is None, 'Failed _check_type1_r1 in "{}"'.format(router) + + test_func = functools.partial(_check_type1_r1, router, '3.0.0.2/32', 800002, 2) + success, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5) + assert result is None, 'Failed _check_type1_r1 in "{}"'.format(router) + + +def exabgp_get_update_prefix(filename, afi, nexthop, prefix): + with open('/tmp/peer2-received.log') as f: + for line in f.readlines(): + output = json.loads(line) + ret = output.get('neighbor') + if ret is None: + continue + ret = ret.get('message') + if ret is None: + continue + ret = ret.get('update') + if ret is None: + continue + ret = ret.get('announce') + if ret is None: + continue + ret = ret.get(afi) + if ret is None: + continue + ret = ret.get(nexthop) + if ret is None: + continue + ret = ret.get(prefix) + if ret is None: + continue + return output + return "Not found" + + +def test_peer2_receive_prefix_sid_type1(): + tgen = get_topogen() + peer2 = tgen.gears['peer2'] + + def _check_type1_peer2(prefix, labelindex): + output = exabgp_get_update_prefix('/tmp/peer2-received.log', 'ipv4 nlri-mpls', '10.0.0.101', prefix) + expected = { + 'type': 'update', + 'neighbor': { + 'ip': '10.0.0.1', + 'message': { + 'update': { + 'attribute': { + 'attribute-0x28-0xE0': '0x010007000000{:08x}'.format(labelindex) + }, + 'announce': { 'ipv4 nlri-mpls': { '10.0.0.101': {} } } + } + } + } + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial(_check_type1_peer2, '3.0.0.1/32', labelindex=1) + success, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5) + assert result is None, 'Failed _check_type1_peer2 in "{}"'.format('peer2') + + test_func = functools.partial(_check_type1_peer2, '3.0.0.2/32', labelindex=2) + success, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5) + assert result is None, 'Failed _check_type1_peer2 in "{}"'.format('peer2') + + +if __name__ == '__main__': + args = ["-s"] + sys.argv[1:] + ret = pytest.main(args) + sys.exit(ret) diff --git a/tests/topotests/ospf6-topo1/test_ospf6_topo1.py b/tests/topotests/ospf6-topo1/test_ospf6_topo1.py index cb0c4af221..2f7a4ce4e3 100755 --- a/tests/topotests/ospf6-topo1/test_ospf6_topo1.py +++ b/tests/topotests/ospf6-topo1/test_ospf6_topo1.py @@ -319,18 +319,18 @@ def test_linux_ipv6_kernel_routingTable(): # Now compare the routing tables (after substituting link-local addresses) for i in range(1, 5): - if topotest.version_cmp(platform.release(), '5.3') < 0: + # Actual output from router + actual = tgen.gears['r{}'.format(i)].run('ip -6 route').rstrip() + if "nhid" in actual: + refTableFile = os.path.join(CWD, 'r{}/ip_6_address.nhg.ref'.format(i)) + else: refTableFile = os.path.join(CWD, 'r{}/ip_6_address.ref'.format(i)) - else: - refTableFile = os.path.join(CWD, 'r{}/ip_6_address.nhg.ref'.format(i)) - if os.path.isfile(refTableFile): + if os.path.isfile(refTableFile): expected = open(refTableFile).read().rstrip() # Fix newlines (make them all the same) expected = ('\n'.join(expected.splitlines())).splitlines(1) - # Actual output from router - actual = tgen.gears['r{}'.format(i)].run('ip -6 route').rstrip() # Mask out Link-Local mac addresses for ll in linklocals: actual = actual.replace(ll[1], "fe80::__(%s)__" % ll[0]) diff --git a/tests/topotests/pim-basic/r1/pimd.conf b/tests/topotests/pim-basic/r1/pimd.conf index cec765699d..f64a46deb3 100644 --- a/tests/topotests/pim-basic/r1/pimd.conf +++ b/tests/topotests/pim-basic/r1/pimd.conf @@ -7,6 +7,10 @@ interface r1-eth0 interface r1-eth1 ip pim ! +interface r1-eth2 + ip igmp + ip pim +! interface lo ip pim ! diff --git a/tests/topotests/pim-basic/r1/zebra.conf b/tests/topotests/pim-basic/r1/zebra.conf index b0a25f12aa..e43041758b 100644 --- a/tests/topotests/pim-basic/r1/zebra.conf +++ b/tests/topotests/pim-basic/r1/zebra.conf @@ -6,6 +6,9 @@ interface r1-eth0 interface r1-eth1 ip address 10.0.30.1/24 ! +interface r1-eth2 + ip address 10.0.40.1/24 +! interface lo ip address 10.254.0.1/32 ! diff --git a/tests/topotests/pim-basic/r3/pimd.conf b/tests/topotests/pim-basic/r3/pimd.conf new file mode 100644 index 0000000000..f94ee99930 --- /dev/null +++ b/tests/topotests/pim-basic/r3/pimd.conf @@ -0,0 +1 @@ +hostname r3 diff --git a/tests/topotests/pim-basic/r3/zebra.conf b/tests/topotests/pim-basic/r3/zebra.conf new file mode 100644 index 0000000000..8e58e8c66a --- /dev/null +++ b/tests/topotests/pim-basic/r3/zebra.conf @@ -0,0 +1,8 @@ +hostname r3 +! +interface r3-eth0 + ip address 10.0.40.4/24 +! +interface lo + ip address 10.254.0.4/32 +! diff --git a/tests/topotests/pim-basic/rp/pimd.conf b/tests/topotests/pim-basic/rp/pimd.conf index 3f1b4d65c9..6e35c97971 100644 --- a/tests/topotests/pim-basic/rp/pimd.conf +++ b/tests/topotests/pim-basic/rp/pimd.conf @@ -7,3 +7,6 @@ interface lo ip pim ! ip pim rp 10.254.0.3 +ip pim register-accept-list ACCEPT + +ip prefix-list ACCEPT seq 5 permit 10.0.20.0/24 le 32 diff --git a/tests/topotests/pim-basic/test_pim.py b/tests/topotests/pim-basic/test_pim.py index 0e0569e234..9101d7e035 100644 --- a/tests/topotests/pim-basic/test_pim.py +++ b/tests/topotests/pim-basic/test_pim.py @@ -46,14 +46,18 @@ class PIMTopo(Topo): "Build function" tgen = get_topogen(self) - for routern in range(1, 3): + for routern in range(1, 4): tgen.add_router('r{}'.format(routern)) tgen.add_router('rp') + # rp ------ r1 -------- r2 + # \ + # --------- r3 # r1 -> .1 # r2 -> .2 # rp -> .3 + # r3 -> .4 # loopback network is 10.254.0.X/32 # # r1 <- sw1 -> r2 @@ -70,6 +74,10 @@ class PIMTopo(Topo): sw.add_link(tgen.gears['r1']) sw.add_link(tgen.gears['rp']) + # 10.0.40.0/24 + sw = tgen.add_switch('sw3') + sw.add_link(tgen.gears['r1']) + sw.add_link(tgen.gears['r3']) def setup_module(mod): "Sets up the pytest environment" @@ -130,12 +138,15 @@ def test_pim_send_mcast_stream(): pytest.skip(tgen.errors) rp = tgen.gears['rp'] + r3 = tgen.gears['r3'] r2 = tgen.gears['r2'] r1 = tgen.gears['r1'] # Let's establish a S,G stream from r2 -> r1 CWD = os.path.dirname(os.path.realpath(__file__)) r2.run("{}/mcast-tx.py --ttl 5 --count 5 --interval 10 229.1.1.1 r2-eth0 > /tmp/bar".format(CWD)) + # And from r3 -> r1 + r3.run("{}/mcast-tx.py --ttl 5 --count 5 --interval 10 229.1.1.1 r3-eth0 > /tmp/bar".format(CWD)) # Let's see that it shows up and we have established some basic state out = r1.vtysh_cmd("show ip pim upstream json", isjson=True) diff --git a/tools/coccinelle/int_to_bool_function.cocci b/tools/coccinelle/int_to_bool_function.cocci new file mode 100644 index 0000000000..f86fe70be2 --- /dev/null +++ b/tools/coccinelle/int_to_bool_function.cocci @@ -0,0 +1,24 @@ +@@ +identifier fn; +typedef bool; +symbol false; +symbol true; +identifier I; +struct thread *thread; +@@ + +- int ++ bool +fn (...) +{ +... when strict + when != I = THREAD_ARG(thread); +( +- return 0; ++ return false; +| +- return 1; ++ return true; +) +?... +} diff --git a/zebra/main.c b/zebra/main.c index 5951c7e280..dab1449194 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -53,6 +53,7 @@ #include "zebra/zebra_rnh.h" #include "zebra/zebra_pbr.h" #include "zebra/zebra_vxlan.h" +#include "zebra/zebra_routemap.h" #if defined(HANDLE_NETLINK_FUZZING) #include "zebra/kernel_netlink.h" @@ -179,7 +180,13 @@ static void sigint(void) access_list_reset(); prefix_list_reset(); - route_map_finish(); + /* + * zebra_routemap_finish will + * 1 set rmap upd timer to 0 so that rmap update wont be scheduled again + * 2 Put off the rmap update thread + * 3 route_map_finish + */ + zebra_routemap_finish(); list_delete(&zrouter.client_list); diff --git a/zebra/redistribute.c b/zebra/redistribute.c index d1148061b9..80cc18a57d 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -173,8 +173,7 @@ void redistribute_update(const struct prefix *p, const struct prefix *src_p, afi = family2afi(p->family); if (!afi) { flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF, - "%s: Unknown AFI/SAFI prefix received\n", - __FUNCTION__); + "%s: Unknown AFI/SAFI prefix received\n", __func__); return; } if (!zebra_check_addr(p)) { diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index e40bf45f59..2f675e2d5a 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1111,7 +1111,8 @@ static int build_label_stack(struct mpls_label_stack *nh_label, * @param nlmsg: nlmsghdr structure to fill in. * @param req_size: The size allocated for the message. */ -static void _netlink_route_build_singlepath(const char *routedesc, int bytelen, +static void _netlink_route_build_singlepath(const struct prefix *p, + const char *routedesc, int bytelen, const struct nexthop *nexthop, struct nlmsghdr *nlmsg, struct rtmsg *rtmsg, @@ -1176,9 +1177,8 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen, if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( - " 5549: _netlink_route_build_singlepath() (%s): " - "nexthop via %s %s if %u(%u)", - routedesc, ipv4_ll_buf, label_buf, + " 5549: _netlink_route_build_singlepath() (%s): %pFX nexthop via %s %s if %u(%u)", + routedesc, p, ipv4_ll_buf, label_buf, nexthop->ifindex, nexthop->vrf_id); return; } @@ -1202,9 +1202,8 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen, if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( - "netlink_route_multipath() (%s): " - "nexthop via %s %s if %u(%u)", - routedesc, inet_ntoa(nexthop->gate.ipv4), + "netlink_route_multipath() (%s): %pFX nexthop via %s %s if %u(%u)", + routedesc, p, inet_ntoa(nexthop->gate.ipv4), label_buf, nexthop->ifindex, nexthop->vrf_id); } @@ -1225,9 +1224,8 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen, if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( - "netlink_route_multipath() (%s): " - "nexthop via %s %s if %u(%u)", - routedesc, inet6_ntoa(nexthop->gate.ipv6), + "netlink_route_multipath() (%s): %pFX nexthop via %s %s if %u(%u)", + routedesc, p, inet6_ntoa(nexthop->gate.ipv6), label_buf, nexthop->ifindex, nexthop->vrf_id); } @@ -1251,9 +1249,9 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen, if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( - "netlink_route_multipath() (%s): " - "nexthop via if %u(%u)", - routedesc, nexthop->ifindex, nexthop->vrf_id); + "netlink_route_multipath() (%s): %pFX nexthop via if %u(%u)", + routedesc, p, nexthop->ifindex, + nexthop->vrf_id); } } @@ -1273,12 +1271,11 @@ static void _netlink_route_build_singlepath(const char *routedesc, int bytelen, * @param src: pointer pointing to a location where * the prefsrc should be stored. */ -static void _netlink_route_build_multipath(const char *routedesc, int bytelen, - const struct nexthop *nexthop, - struct rtattr *rta, - struct rtnexthop *rtnh, - struct rtmsg *rtmsg, - const union g_addr **src) +static void +_netlink_route_build_multipath(const struct prefix *p, const char *routedesc, + int bytelen, const struct nexthop *nexthop, + struct rtattr *rta, struct rtnexthop *rtnh, + struct rtmsg *rtmsg, const union g_addr **src) { mpls_lse_t out_lse[MPLS_MAX_LABELS]; char label_buf[256]; @@ -1340,6 +1337,8 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen, bytelen); rtnh->rtnh_len += sizeof(struct rtattr) + bytelen; rtnh->rtnh_ifindex = nexthop->ifindex; + if (nexthop->weight) + rtnh->rtnh_hops = nexthop->weight - 1; if (nexthop->rmap_src.ipv4.s_addr != INADDR_ANY) *src = &nexthop->rmap_src; @@ -1348,9 +1347,8 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen, if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( - " 5549: netlink_route_build_multipath() (%s): " - "nexthop via %s %s if %u", - routedesc, ipv4_ll_buf, label_buf, + " 5549: netlink_route_build_multipath() (%s): %pFX nexthop via %s %s if %u", + routedesc, p, ipv4_ll_buf, label_buf, nexthop->ifindex); return; } @@ -1367,9 +1365,8 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen, if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( - "netlink_route_multipath() (%s): " - "nexthop via %s %s if %u", - routedesc, inet_ntoa(nexthop->gate.ipv4), + "netlink_route_multipath() (%s): %pFX nexthop via %s %s if %u", + routedesc, p, inet_ntoa(nexthop->gate.ipv4), label_buf, nexthop->ifindex); } if (nexthop->type == NEXTHOP_TYPE_IPV6 @@ -1385,9 +1382,8 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen, if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( - "netlink_route_multipath() (%s): " - "nexthop via %s %s if %u", - routedesc, inet6_ntoa(nexthop->gate.ipv6), + "netlink_route_multipath() (%s): %pFX nexthop via %s %s if %u", + routedesc, p, inet6_ntoa(nexthop->gate.ipv6), label_buf, nexthop->ifindex); } @@ -1408,16 +1404,16 @@ static void _netlink_route_build_multipath(const char *routedesc, int bytelen, if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( - "netlink_route_multipath() (%s): " - "nexthop via if %u", - routedesc, nexthop->ifindex); + "netlink_route_multipath() (%s): %pFX nexthop via if %u", + routedesc, p, nexthop->ifindex); } if (nexthop->weight) rtnh->rtnh_hops = nexthop->weight - 1; } -static inline void _netlink_mpls_build_singlepath(const char *routedesc, +static inline void _netlink_mpls_build_singlepath(const struct prefix *p, + const char *routedesc, const zebra_nhlfe_t *nhlfe, struct nlmsghdr *nlmsg, struct rtmsg *rtmsg, @@ -1428,23 +1424,24 @@ static inline void _netlink_mpls_build_singlepath(const char *routedesc, family = NHLFE_FAMILY(nhlfe); bytelen = (family == AF_INET ? 4 : 16); - _netlink_route_build_singlepath(routedesc, bytelen, nhlfe->nexthop, + _netlink_route_build_singlepath(p, routedesc, bytelen, nhlfe->nexthop, nlmsg, rtmsg, req_size, cmd); } static inline void -_netlink_mpls_build_multipath(const char *routedesc, const zebra_nhlfe_t *nhlfe, - struct rtattr *rta, struct rtnexthop *rtnh, - struct rtmsg *rtmsg, const union g_addr **src) +_netlink_mpls_build_multipath(const struct prefix *p, const char *routedesc, + const zebra_nhlfe_t *nhlfe, struct rtattr *rta, + struct rtnexthop *rtnh, struct rtmsg *rtmsg, + const union g_addr **src) { int bytelen; uint8_t family; family = NHLFE_FAMILY(nhlfe); bytelen = (family == AF_INET ? 4 : 16); - _netlink_route_build_multipath(routedesc, bytelen, nhlfe->nexthop, rta, - rtnh, rtmsg, src); + _netlink_route_build_multipath(p, routedesc, bytelen, nhlfe->nexthop, + rta, rtnh, rtmsg, src); } @@ -1644,6 +1641,10 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx) } if (kernel_nexthops_supported()) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug( + "netlink_route_multipath(): %pFX nhg_id is %u", + p, dplane_ctx_get_nhe_id(ctx)); /* Kernel supports nexthop objects */ addattr32(&req.n, sizeof(req), RTA_NH_ID, dplane_ctx_get_nhe_id(ctx)); @@ -1730,7 +1731,7 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx) : "single-path"; _netlink_route_build_singlepath( - routedesc, bytelen, nexthop, &req.n, + p, routedesc, bytelen, nexthop, &req.n, &req.r, sizeof(req), cmd); nexthop_num++; break; @@ -1800,8 +1801,8 @@ static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx) nexthop_num++; _netlink_route_build_multipath( - routedesc, bytelen, nexthop, rta, rtnh, - &req.r, &src1); + p, routedesc, bytelen, nexthop, rta, + rtnh, &req.r, &src1); rtnh = RTNH_NEXT(rtnh); if (!setsrc && src1) { @@ -3464,6 +3465,7 @@ int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx) unsigned int nexthop_num; const char *routedesc; int route_type; + struct prefix p = {0}; struct { struct nlmsghdr n; @@ -3550,8 +3552,7 @@ int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx) NEXTHOP_FLAG_FIB)))) { /* Add the gateway */ _netlink_mpls_build_singlepath( - routedesc, nhlfe, - &req.n, &req.r, + &p, routedesc, nhlfe, &req.n, &req.r, sizeof(req), cmd); nexthop_num++; @@ -3591,9 +3592,9 @@ int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx) nexthop_num++; /* Build the multipath */ - _netlink_mpls_build_multipath(routedesc, nhlfe, - rta, rtnh, &req.r, - &src1); + _netlink_mpls_build_multipath(&p, routedesc, + nhlfe, rta, rtnh, + &req.r, &src1); rtnh = RTNH_NEXT(rtnh); } } diff --git a/zebra/zebra_ptm_redistribute.c b/zebra/zebra_ptm_redistribute.c index 01d5114b9f..eabc2e005e 100644 --- a/zebra/zebra_ptm_redistribute.c +++ b/zebra/zebra_ptm_redistribute.c @@ -59,6 +59,9 @@ static int zsend_interface_bfd_update(int cmd, struct zserv *client, stream_put(s, &sp->u.prefix, blen); stream_putc(s, sp->prefixlen); + /* c-bit bullshit */ + stream_putc(s, 0); + /* Write packet size. */ stream_putw_at(s, 0, stream_get_endp(s)); diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 6cfc68eb74..c758e25839 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -1030,7 +1030,7 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type, default: flog_err(EC_ZEBRA_RNH_UNKNOWN_FAMILY, "%s: Unknown family (%d) notification attempted\n", - __FUNCTION__, rn->p.family); + __func__, rn->p.family); break; } if (re) { diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index 2963d83828..500c2c84a1 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -1793,6 +1793,15 @@ static void zebra_route_map_set_delay_timer(uint32_t value) } } +void zebra_routemap_finish(void) +{ + /* Set zebra_rmap_update_timer to 0 so that it wont schedule again */ + zebra_rmap_update_timer = 0; + /* Thread off if any scheduled already */ + THREAD_TIMER_OFF(zebra_t_rmap_update); + route_map_finish(); +} + void zebra_route_map_write_delay_timer(struct vty *vty) { if (vty && (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)) diff --git a/zebra/zebra_routemap.h b/zebra/zebra_routemap.h index 6a630e1ac0..56e805ea03 100644 --- a/zebra/zebra_routemap.h +++ b/zebra/zebra_routemap.h @@ -56,4 +56,5 @@ zebra_nht_route_map_check(afi_t afi, int client_proto, const struct prefix *p, } #endif +extern void zebra_routemap_finish(void); #endif diff --git a/zebra/zserv.h b/zebra/zserv.h index 6a075cc9a7..6ab7fbd918 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -314,7 +314,7 @@ extern void zserv_read_file(char *input); #endif /* TODO */ -int zebra_finalize(struct thread *event); +__attribute__((__noreturn__)) int zebra_finalize(struct thread *event); /* * Graceful restart functions. |
