diff options
235 files changed, 6813 insertions, 1433 deletions
diff --git a/bgpd/bgp_addpath.c b/bgpd/bgp_addpath.c index aaa77b04d..75fdb0bb4 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 786873a00..f61d68e18 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 8d1c83cf5..9ee6a24bc 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 c98359875..6223dc94a 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 be80675b5..44962f5af 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 f327751f3..9df352fcd 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 a1278874c..0bdd079e0 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. */ @@ -4076,7 +4130,7 @@ void bgp_attr_finish(void) /* Make attribute packet. */ void bgp_dump_routes_attr(struct stream *s, struct attr *attr, - struct prefix *prefix) + const struct prefix *prefix) { unsigned long cp; unsigned long len; diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 2e91f56df..04b3a20d6 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -324,8 +324,8 @@ extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *, struct prefix *, afi_t, safi_t, struct peer *, struct prefix_rd *, mpls_label_t *, uint32_t, int, uint32_t); -extern void bgp_dump_routes_attr(struct stream *, struct attr *, - struct prefix *); +extern void bgp_dump_routes_attr(struct stream *s, struct attr *attr, + const struct prefix *p); extern bool attrhash_cmp(const void *arg1, const void *arg2); extern unsigned int attrhash_key_make(const void *); extern void attr_show_all(struct vty *); @@ -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 ec9656a98..7239ddef9 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) @@ -186,7 +186,7 @@ uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, uint8_t *sticky) * one. */ for (i = 0; i < ecom->size; i++) { - uint8_t *pnt; + const uint8_t *pnt; uint8_t type, sub_type; uint32_t seq_num; diff --git a/bgpd/bgp_attr_evpn.h b/bgpd/bgp_attr_evpn.h index 25654ba70..c1bfd8376 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 1f650aaeb..a200589bd 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 caa5651e3..f2fa959b4 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 24a9cab5d..32865da37 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 cc37e352e..cbe18e23c 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_clist.c b/bgpd/bgp_clist.c index 5c461dbe7..cf4d44ea2 100644 --- a/bgpd/bgp_clist.c +++ b/bgpd/bgp_clist.c @@ -311,9 +311,9 @@ static void community_list_delete(struct community_list_master *cm, community_list_free(list); } -static int community_list_empty_p(struct community_list *list) +static bool community_list_empty_p(struct community_list *list) { - return (list->head == NULL && list->tail == NULL) ? 1 : 0; + return list->head == NULL && list->tail == NULL; } /* Delete community-list entry from the list. */ @@ -497,7 +497,7 @@ static char *community_str_get(struct community *com, int i) /* Internal function to perform regular expression match for * a single community. */ -static int community_regexp_include(regex_t *reg, struct community *com, int i) +static bool community_regexp_include(regex_t *reg, struct community *com, int i) { char *str; int rv; @@ -514,16 +514,12 @@ static int community_regexp_include(regex_t *reg, struct community *com, int i) XFREE(MTYPE_COMMUNITY_STR, str); - if (rv == 0) - return 1; - - /* No match. */ - return 0; + return rv == 0; } /* Internal function to perform regular expression match for community attribute. */ -static int community_regexp_match(struct community *com, regex_t *reg) +static bool community_regexp_match(struct community *com, regex_t *reg) { const char *str; @@ -536,10 +532,10 @@ static int community_regexp_match(struct community *com, regex_t *reg) /* Regular expression match. */ if (regexec(reg, str, 0, NULL, 0) == 0) - return 1; + return true; /* No match. */ - return 0; + return false; } static char *lcommunity_str_get(struct lcommunity *lcom, int i) @@ -549,7 +545,7 @@ static char *lcommunity_str_get(struct lcommunity *lcom, int i) uint32_t localdata1; uint32_t localdata2; char *str; - uint8_t *ptr; + const uint8_t *ptr; char *pnt; ptr = lcom->val + (i * LCOMMUNITY_SIZE); @@ -574,8 +570,8 @@ static char *lcommunity_str_get(struct lcommunity *lcom, int i) /* Internal function to perform regular expression match for * a single community. */ -static int lcommunity_regexp_include(regex_t *reg, struct lcommunity *lcom, - int i) +static bool lcommunity_regexp_include(regex_t *reg, struct lcommunity *lcom, + int i) { char *str; @@ -589,15 +585,15 @@ static int lcommunity_regexp_include(regex_t *reg, struct lcommunity *lcom, /* Regular expression match. */ if (regexec(reg, str, 0, NULL, 0) == 0) { XFREE(MTYPE_LCOMMUNITY_STR, str); - return 1; + return true; } XFREE(MTYPE_LCOMMUNITY_STR, str); /* No match. */ - return 0; + return false; } -static int lcommunity_regexp_match(struct lcommunity *com, regex_t *reg) +static bool lcommunity_regexp_match(struct lcommunity *com, regex_t *reg) { const char *str; @@ -610,14 +606,14 @@ static int lcommunity_regexp_match(struct lcommunity *com, regex_t *reg) /* Regular expression match. */ if (regexec(reg, str, 0, NULL, 0) == 0) - return 1; + return true; /* No match. */ - return 0; + return false; } -static int ecommunity_regexp_match(struct ecommunity *ecom, regex_t *reg) +static bool ecommunity_regexp_match(struct ecommunity *ecom, regex_t *reg) { const char *str; @@ -630,10 +626,10 @@ static int ecommunity_regexp_match(struct ecommunity *ecom, regex_t *reg) /* Regular expression match. */ if (regexec(reg, str, 0, NULL, 0) == 0) - return 1; + return true; /* No match. */ - return 0; + return false; } #if 0 @@ -718,125 +714,113 @@ community_regexp_delete (struct community *com, regex_t * reg) /* When given community attribute matches to the community-list return 1 else return 0. */ -int community_list_match(struct community *com, struct community_list *list) +bool community_list_match(struct community *com, struct community_list *list) { struct community_entry *entry; for (entry = list->head; entry; entry = entry->next) { if (entry->any) - return entry->direct == COMMUNITY_PERMIT ? 1 : 0; + return entry->direct == COMMUNITY_PERMIT; if (entry->style == COMMUNITY_LIST_STANDARD) { if (community_include(entry->u.com, COMMUNITY_INTERNET)) - return entry->direct == COMMUNITY_PERMIT ? 1 - : 0; + return entry->direct == COMMUNITY_PERMIT; if (community_match(com, entry->u.com)) - return entry->direct == COMMUNITY_PERMIT ? 1 - : 0; + return entry->direct == COMMUNITY_PERMIT; } else if (entry->style == COMMUNITY_LIST_EXPANDED) { if (community_regexp_match(com, entry->reg)) - return entry->direct == COMMUNITY_PERMIT ? 1 - : 0; + return entry->direct == COMMUNITY_PERMIT; } } - return 0; + return false; } -int lcommunity_list_match(struct lcommunity *lcom, struct community_list *list) +bool lcommunity_list_match(struct lcommunity *lcom, struct community_list *list) { struct community_entry *entry; for (entry = list->head; entry; entry = entry->next) { if (entry->any) - return entry->direct == COMMUNITY_PERMIT ? 1 : 0; + return entry->direct == COMMUNITY_PERMIT; if (entry->style == LARGE_COMMUNITY_LIST_STANDARD) { if (lcommunity_match(lcom, entry->u.lcom)) - return entry->direct == COMMUNITY_PERMIT ? 1 - : 0; + return entry->direct == COMMUNITY_PERMIT; } else if (entry->style == LARGE_COMMUNITY_LIST_EXPANDED) { if (lcommunity_regexp_match(lcom, entry->reg)) - return entry->direct == COMMUNITY_PERMIT ? 1 - : 0; + return entry->direct == COMMUNITY_PERMIT; } } - return 0; + return false; } /* Perform exact matching. In case of expanded large-community-list, do * same thing as lcommunity_list_match(). */ -int lcommunity_list_exact_match(struct lcommunity *lcom, - struct community_list *list) +bool lcommunity_list_exact_match(struct lcommunity *lcom, + struct community_list *list) { struct community_entry *entry; for (entry = list->head; entry; entry = entry->next) { if (entry->any) - return entry->direct == COMMUNITY_PERMIT ? 1 : 0; + return entry->direct == COMMUNITY_PERMIT; if (entry->style == LARGE_COMMUNITY_LIST_STANDARD) { if (lcommunity_cmp(lcom, entry->u.com)) - return entry->direct == COMMUNITY_PERMIT ? 1 - : 0; + return entry->direct == COMMUNITY_PERMIT; } else if (entry->style == LARGE_COMMUNITY_LIST_EXPANDED) { if (lcommunity_regexp_match(lcom, entry->reg)) - return entry->direct == COMMUNITY_PERMIT ? 1 - : 0; + return entry->direct == COMMUNITY_PERMIT; } } - return 0; + return false; } -int ecommunity_list_match(struct ecommunity *ecom, struct community_list *list) +bool ecommunity_list_match(struct ecommunity *ecom, struct community_list *list) { struct community_entry *entry; for (entry = list->head; entry; entry = entry->next) { if (entry->any) - return entry->direct == COMMUNITY_PERMIT ? 1 : 0; + return entry->direct == COMMUNITY_PERMIT; if (entry->style == EXTCOMMUNITY_LIST_STANDARD) { if (ecommunity_match(ecom, entry->u.ecom)) - return entry->direct == COMMUNITY_PERMIT ? 1 - : 0; + return entry->direct == COMMUNITY_PERMIT; } else if (entry->style == EXTCOMMUNITY_LIST_EXPANDED) { if (ecommunity_regexp_match(ecom, entry->reg)) - return entry->direct == COMMUNITY_PERMIT ? 1 - : 0; + return entry->direct == COMMUNITY_PERMIT; } } - return 0; + return false; } /* Perform exact matching. In case of expanded community-list, do same thing as community_list_match(). */ -int community_list_exact_match(struct community *com, - struct community_list *list) +bool community_list_exact_match(struct community *com, + struct community_list *list) { struct community_entry *entry; for (entry = list->head; entry; entry = entry->next) { if (entry->any) - return entry->direct == COMMUNITY_PERMIT ? 1 : 0; + return entry->direct == COMMUNITY_PERMIT; if (entry->style == COMMUNITY_LIST_STANDARD) { if (community_include(entry->u.com, COMMUNITY_INTERNET)) - return entry->direct == COMMUNITY_PERMIT ? 1 - : 0; + return entry->direct == COMMUNITY_PERMIT; if (community_cmp(com, entry->u.com)) - return entry->direct == COMMUNITY_PERMIT ? 1 - : 0; + return entry->direct == COMMUNITY_PERMIT; } else if (entry->style == COMMUNITY_LIST_EXPANDED) { if (community_regexp_match(com, entry->reg)) - return entry->direct == COMMUNITY_PERMIT ? 1 - : 0; + return entry->direct == COMMUNITY_PERMIT; } } - return 0; + return false; } /* Delete all permitted communities in the list from com. */ @@ -900,8 +884,8 @@ struct community *community_list_match_delete(struct community *com, /* To avoid duplicated entry in the community-list, this function compares specified entry to existing entry. */ -static int community_list_dup_check(struct community_list *list, - struct community_entry *new) +static bool community_list_dup_check(struct community_list *list, + struct community_entry *new) { struct community_entry *entry; @@ -916,32 +900,32 @@ static int community_list_dup_check(struct community_list *list, continue; if (entry->any) - return 1; + return true; switch (entry->style) { case COMMUNITY_LIST_STANDARD: if (community_cmp(entry->u.com, new->u.com)) - return 1; + return true; break; case LARGE_COMMUNITY_LIST_STANDARD: if (lcommunity_cmp(entry->u.lcom, new->u.lcom)) - return 1; + return true; break; case EXTCOMMUNITY_LIST_STANDARD: if (ecommunity_cmp(entry->u.ecom, new->u.ecom)) - return 1; + return true; break; case COMMUNITY_LIST_EXPANDED: case EXTCOMMUNITY_LIST_EXPANDED: case LARGE_COMMUNITY_LIST_EXPANDED: if (strcmp(entry->config, new->config) == 0) - return 1; + return true; break; default: break; } } - return 0; + return false; } /* Set community-list. */ @@ -1104,7 +1088,7 @@ struct lcommunity *lcommunity_list_match_delete(struct lcommunity *lcom, } /* Helper to check if every octet do not exceed UINT_MAX */ -static int lcommunity_list_valid(const char *community) +static bool lcommunity_list_valid(const char *community) { int octets = 0; char **splits; @@ -1114,10 +1098,10 @@ static int lcommunity_list_valid(const char *community) for (int i = 0; i < num; i++) { if (strtoul(splits[i], NULL, 10) > UINT_MAX) - return 0; + return false; if (strlen(splits[i]) == 0) - return 0; + return false; octets++; XFREE(MTYPE_TMP, splits[i]); @@ -1125,9 +1109,9 @@ static int lcommunity_list_valid(const char *community) XFREE(MTYPE_TMP, splits); if (octets < 3) - return 0; + return false; - return 1; + return true; } /* Set lcommunity-list. */ diff --git a/bgpd/bgp_clist.h b/bgpd/bgp_clist.h index c5718aeca..4cb5d7c59 100644 --- a/bgpd/bgp_clist.h +++ b/bgpd/bgp_clist.h @@ -165,13 +165,13 @@ extern struct community_list * community_list_lookup(struct community_list_handler *c, const char *name, uint32_t name_hash, int master); -extern int community_list_match(struct community *, struct community_list *); -extern int ecommunity_list_match(struct ecommunity *, struct community_list *); -extern int lcommunity_list_match(struct lcommunity *, struct community_list *); -extern int community_list_exact_match(struct community *, - struct community_list *); -extern int lcommunity_list_exact_match(struct lcommunity *lcom, - struct community_list *list); +extern bool community_list_match(struct community *, struct community_list *); +extern bool ecommunity_list_match(struct ecommunity *, struct community_list *); +extern bool lcommunity_list_match(struct lcommunity *, struct community_list *); +extern bool community_list_exact_match(struct community *, + struct community_list *); +extern bool lcommunity_list_exact_match(struct lcommunity *lcom, + struct community_list *list); extern struct community *community_list_match_delete(struct community *, struct community_list *); extern struct lcommunity * diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c index c145c47d0..195c0f394 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 74a3a6b50..31a061370 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 466fecc58..bae1079a1 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -170,12 +170,22 @@ static const struct message bgp_notify_capability_msg[] = { {BGP_NOTIFY_CAPABILITY_MALFORMED_CODE, "/Malformed Capability Value"}, {0}}; +static const struct message bgp_notify_fsm_msg[] = { + {BGP_NOTIFY_FSM_ERR_SUBCODE_UNSPECIFIC, "/Unspecific"}, + {BGP_NOTIFY_FSM_ERR_SUBCODE_OPENSENT, + "/Receive Unexpected Message in OpenSent State"}, + {BGP_NOTIFY_FSM_ERR_SUBCODE_OPENCONFIRM, + "/Receive Unexpected Message in OpenConfirm State"}, + {BGP_NOTIFY_FSM_ERR_SUBCODE_ESTABLISHED, + "/Receive Unexpected Message in Established State"}, + {0}}; + /* Origin strings. */ 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) { @@ -305,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; @@ -316,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; @@ -338,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'; @@ -445,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) @@ -471,7 +481,8 @@ const char *bgp_notify_subcode_str(char code, char subcode) case BGP_NOTIFY_HOLD_ERR: break; case BGP_NOTIFY_FSM_ERR: - break; + return lookup_msg(bgp_notify_fsm_msg, subcode, + "Unrecognized Error Subcode"); case BGP_NOTIFY_CEASE: return lookup_msg(bgp_notify_cease_msg, subcode, "Unrecognized Error Subcode"); @@ -550,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]; @@ -590,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, @@ -2395,7 +2404,7 @@ void bgp_debug_init(void) /* Return true if this prefix is on the per_prefix_list of prefixes to debug * for BGP_DEBUG_TYPE */ -static int bgp_debug_per_prefix(struct prefix *p, +static int bgp_debug_per_prefix(const struct prefix *p, unsigned long term_bgp_debug_type, unsigned int BGP_DEBUG_TYPE, struct list *per_prefix_list) @@ -2480,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, const struct prefix *p, + struct update_group *updgrp, unsigned int inbound) { char *host = NULL; @@ -2492,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 */ @@ -2500,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; } @@ -2513,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(const 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 1e6482e96..51f939692 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, const struct prefix *p, + struct update_group *updgrp, unsigned int inbound); +extern bool bgp_debug_bestpath(struct prefix *p); +extern bool bgp_debug_zebra(const 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 2711cf7a6..fc6649474 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 @@ -555,7 +555,7 @@ struct ecommunity *ecommunity_str2com(const char *str, int type, return ecom; } -static int ecommunity_rt_soo_str(char *buf, size_t bufsz, uint8_t *pnt, +static int ecommunity_rt_soo_str(char *buf, size_t bufsz, const uint8_t *pnt, int type, int sub_type, int format) { int len = 0; @@ -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 ae64f41ca..df0da091d 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 664d62fd1..5972359f7 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -496,7 +496,7 @@ static void unmap_vni_from_rt(struct bgp *bgp, struct bgpevpn *vpn, } static void bgp_evpn_get_rmac_nexthop(struct bgpevpn *vpn, - struct prefix_evpn *p, + const struct prefix_evpn *p, struct attr *attr, uint8_t flags) { struct bgp *bgp_vrf = vpn->bgp_vrf; @@ -583,7 +583,7 @@ static void evpn_convert_nexthop_to_ipv6(struct attr *attr) * Add (update) or delete MACIP from zebra. */ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, - struct prefix_evpn *p, + const struct prefix_evpn *p, struct in_addr remote_vtep_ip, int add, uint8_t flags, uint32_t seq) { @@ -651,8 +651,8 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, * Add (update) or delete remote VTEP from zebra. */ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn, - struct prefix_evpn *p, - int flood_control, int add) + const struct prefix_evpn *p, + int flood_control, int add) { struct stream *s; @@ -930,7 +930,8 @@ static void add_mac_mobility_to_attr(uint32_t seq_num, struct attr *attr) /* Install EVPN route into zebra. */ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn, - struct prefix_evpn *p, struct bgp_path_info *pi) + const struct prefix_evpn *p, + struct bgp_path_info *pi) { int ret; uint8_t flags; @@ -970,7 +971,7 @@ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn, /* Uninstall EVPN route from zebra. */ static int evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn, - struct prefix_evpn *p, + const struct prefix_evpn *p, struct in_addr remote_vtep_ip) { int ret; @@ -1054,9 +1055,8 @@ static int is_vtep_present_in_list(struct list *list, * Best path for ES route was changed, * update the list of VTEPs for this ES */ -static int evpn_es_install_vtep(struct bgp *bgp, - struct evpnes *es, - struct prefix_evpn *p, +static int evpn_es_install_vtep(struct bgp *bgp, struct evpnes *es, + const struct prefix_evpn *p, struct in_addr rvtep) { struct in_addr *vtep_ip; @@ -1157,7 +1157,7 @@ static int evpn_es_route_select_install(struct bgp *bgp, if (new_select && new_select->type == ZEBRA_ROUTE_BGP && new_select->sub_type == BGP_ROUTE_IMPORTED) { ret = evpn_es_install_vtep(bgp, es, - (struct prefix_evpn *)&rn->p, + (const struct prefix_evpn *)&rn->p, new_select->attr->nexthop); } else { if (old_select && old_select->type == ZEBRA_ROUTE_BGP @@ -2555,7 +2555,7 @@ bgp_create_evpn_bgp_path_info(struct bgp_path_info *parent_pi, /* Install EVPN route entry in ES */ static int install_evpn_route_entry_in_es(struct bgp *bgp, struct evpnes *es, - struct prefix_evpn *p, + const struct prefix_evpn *p, struct bgp_path_info *parent_pi) { int ret = 0; @@ -2619,7 +2619,7 @@ static int install_evpn_route_entry_in_es(struct bgp *bgp, struct evpnes *es, * Install route entry into the VRF routing table and invoke route selection. */ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, - struct prefix_evpn *evp, + const struct prefix_evpn *evp, struct bgp_path_info *parent_pi) { struct bgp_node *rn; @@ -2726,7 +2726,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, * Install route entry into the VNI routing table and invoke route selection. */ static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, - struct prefix_evpn *p, + const struct prefix_evpn *p, struct bgp_path_info *parent_pi) { struct bgp_node *rn; @@ -2782,7 +2782,7 @@ static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, /* Uninstall EVPN route entry from ES route table */ static int uninstall_evpn_route_entry_in_es(struct bgp *bgp, struct evpnes *es, - struct prefix_evpn *p, + const struct prefix_evpn *p, struct bgp_path_info *parent_pi) { int ret; @@ -2825,7 +2825,7 @@ static int uninstall_evpn_route_entry_in_es(struct bgp *bgp, struct evpnes *es, * to zebra, if appropriate. */ static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, - struct prefix_evpn *evp, + const struct prefix_evpn *evp, struct bgp_path_info *parent_pi) { struct bgp_node *rn; @@ -2895,7 +2895,7 @@ static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, * to zebra, if appropriate. */ static int uninstall_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, - struct prefix_evpn *p, + const struct prefix_evpn *p, struct bgp_path_info *parent_pi) { struct bgp_node *rn; @@ -2932,7 +2932,7 @@ static int uninstall_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, /* * Given a prefix, see if it belongs to ES. */ -static int is_prefix_matching_for_es(struct prefix_evpn *p, +static int is_prefix_matching_for_es(const struct prefix_evpn *p, struct evpnes *es) { /* if not an ES route return false */ @@ -3153,7 +3153,7 @@ static int install_uninstall_routes_for_es(struct bgp *bgp, * route into bgp vrf table and remote rmac in bridge table. */ static int bgp_evpn_route_rmac_self_check(struct bgp *bgp_vrf, - struct prefix_evpn *evp, + const struct prefix_evpn *evp, struct bgp_path_info *pi) { /* evpn route could have learnt prior to L3vni has come up, @@ -4465,7 +4465,7 @@ static void update_autort_vni(struct hash_bucket *bucket, struct bgp *bgp) */ /* withdraw type-5 route corresponding to ip prefix */ -void bgp_evpn_withdraw_type5_route(struct bgp *bgp_vrf, struct prefix *p, +void bgp_evpn_withdraw_type5_route(struct bgp *bgp_vrf, const struct prefix *p, afi_t afi, safi_t safi) { int ret = 0; @@ -4535,7 +4535,7 @@ void bgp_evpn_install_uninstall_default_route(struct bgp *bgp_vrf, afi_t afi, * path in the case of the attr. In the case of a local prefix (when we * are advertising local subnets), the src_attr will be NULL. */ -void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, struct prefix *p, +void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, const struct prefix *p, struct attr *src_attr, afi_t afi, safi_t safi) { @@ -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; } } @@ -4882,7 +4900,7 @@ char *bgp_evpn_label2str(mpls_label_t *label, uint32_t num_labels, char *buf, * Function to convert evpn route to json format. * NOTE: We don't use prefix2str as the output here is a bit different. */ -void bgp_evpn_route2json(struct prefix_evpn *p, json_object *json) +void bgp_evpn_route2json(const struct prefix_evpn *p, json_object *json) { char buf1[ETHER_ADDR_STRLEN]; char buf2[PREFIX2STR_BUFFER]; @@ -4947,7 +4965,7 @@ void bgp_evpn_route2json(struct prefix_evpn *p, json_object *json) * Function to convert evpn route to string. * NOTE: We don't use prefix2str as the output here is a bit different. */ -char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len) +char *bgp_evpn_route2str(const struct prefix_evpn *p, char *buf, int len) { char buf1[ETHER_ADDR_STRLEN]; char buf2[PREFIX2STR_BUFFER]; diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index b030f0a33..308ced098 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -140,11 +140,12 @@ static inline bool is_route_injectable_into_evpn(struct bgp_path_info *pi) } extern void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf, - struct prefix *p, + const struct prefix *p, struct attr *src_attr, afi_t afi, safi_t safi); -extern void bgp_evpn_withdraw_type5_route(struct bgp *bgp_vrf, struct prefix *p, - afi_t afi, safi_t safi); +extern void bgp_evpn_withdraw_type5_route(struct bgp *bgp_vrf, + const struct prefix *p, afi_t afi, + safi_t safi); extern void bgp_evpn_withdraw_type5_routes(struct bgp *bgp_vrf, afi_t afi, safi_t safi); extern void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi, @@ -153,8 +154,9 @@ extern void bgp_evpn_vrf_delete(struct bgp *bgp_vrf); extern void bgp_evpn_handle_router_id_update(struct bgp *bgp, int withdraw); extern char *bgp_evpn_label2str(mpls_label_t *label, uint32_t num_labels, char *buf, int len); -extern char *bgp_evpn_route2str(struct prefix_evpn *p, char *buf, int len); -extern void bgp_evpn_route2json(struct prefix_evpn *p, json_object *json); +extern char *bgp_evpn_route2str(const struct prefix_evpn *p, char *buf, + int len); +extern void bgp_evpn_route2json(const struct prefix_evpn *p, json_object *json); extern void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p, struct prefix_rd *prd, mpls_label_t *label, uint32_t num_labels, struct attr *attr, diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h index 76cf8b2cd..ea1ae087f 100644 --- a/bgpd/bgp_evpn_private.h +++ b/bgpd/bgp_evpn_private.h @@ -366,7 +366,7 @@ static inline void encode_na_flag_extcomm(struct ecommunity_val *eval, eval->val[2] |= ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG; } -static inline void ip_prefix_from_type5_prefix(struct prefix_evpn *evp, +static inline void ip_prefix_from_type5_prefix(const struct prefix_evpn *evp, struct prefix *ip) { memset(ip, 0, sizeof(struct prefix)); @@ -392,7 +392,7 @@ static inline int is_evpn_prefix_default(const struct prefix *evp) 1 : 0); } -static inline void ip_prefix_from_type2_prefix(struct prefix_evpn *evp, +static inline void ip_prefix_from_type2_prefix(const struct prefix_evpn *evp, struct prefix *ip) { memset(ip, 0, sizeof(struct prefix)); @@ -409,7 +409,7 @@ static inline void ip_prefix_from_type2_prefix(struct prefix_evpn *evp, } } -static inline void ip_prefix_from_evpn_prefix(struct prefix_evpn *evp, +static inline void ip_prefix_from_evpn_prefix(const struct prefix_evpn *evp, struct prefix *ip) { if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) @@ -432,8 +432,9 @@ static inline void build_evpn_type2_prefix(struct prefix_evpn *p, memcpy(&p->prefix.macip_addr.ip, ip, sizeof(*ip)); } -static inline void build_type5_prefix_from_ip_prefix(struct prefix_evpn *evp, - struct prefix *ip_prefix) +static inline void +build_type5_prefix_from_ip_prefix(struct prefix_evpn *evp, + const struct prefix *ip_prefix) { struct ipaddr ip; diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 7ed37319b..70bd7b219 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -59,7 +59,7 @@ struct vni_walk_ctx { static void display_vrf_import_rt(struct vty *vty, struct vrf_irt_node *irt, json_object *json) { - uint8_t *pnt; + const uint8_t *pnt; uint8_t type, sub_type; struct ecommunity_as eas; struct ecommunity_ip eip; @@ -167,7 +167,7 @@ static void show_vrf_import_rt_entry(struct hash_bucket *bucket, void *args[]) static void display_import_rt(struct vty *vty, struct irt_node *irt, json_object *json) { - uint8_t *pnt; + const uint8_t *pnt; uint8_t type, sub_type; struct ecommunity_as eas; struct ecommunity_ip eip; @@ -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 a03551e79..7de8dc2c8 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 3c49e357f..9357a2d38 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.h b/bgpd/bgp_flowspec.h index bc201b739..94c571f2f 100644 --- a/bgpd/bgp_flowspec.h +++ b/bgpd/bgp_flowspec.h @@ -43,7 +43,7 @@ extern void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len, char *return_string, int format, json_object *json_path); -extern void route_vty_out_flowspec(struct vty *vty, struct prefix *p, +extern void route_vty_out_flowspec(struct vty *vty, const struct prefix *p, struct bgp_path_info *path, int display, json_object *json_paths); extern int bgp_fs_config_write_pbr(struct vty *vty, struct bgp *bgp, diff --git a/bgpd/bgp_flowspec_util.c b/bgpd/bgp_flowspec_util.c index 002aae561..79d5268c7 100644 --- a/bgpd/bgp_flowspec_util.c +++ b/bgpd/bgp_flowspec_util.c @@ -76,9 +76,8 @@ static int bgp_flowspec_call_non_opaque_decode(uint8_t *nlri_content, int len, return ret; } -bool bgp_flowspec_contains_prefix(struct prefix *pfs, - struct prefix *input, - int prefix_check) +bool bgp_flowspec_contains_prefix(const struct prefix *pfs, + struct prefix *input, int prefix_check) { uint32_t offset = 0; int type; @@ -599,8 +598,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 +608,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 +616,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 2ce911da4..0e78c7a53 100644 --- a/bgpd/bgp_flowspec_util.h +++ b/bgpd/bgp_flowspec_util.h @@ -50,12 +50,11 @@ struct bgp_pbr_entry_main; extern int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len, struct bgp_pbr_entry_main *bpem); -extern bool bgp_flowspec_contains_prefix(struct prefix *pfs, +extern bool bgp_flowspec_contains_prefix(const 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_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c index 80384c12c..c453c4e81 100644 --- a/bgpd/bgp_flowspec_vty.c +++ b/bgpd/bgp_flowspec_vty.c @@ -252,7 +252,7 @@ void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len, } } -void route_vty_out_flowspec(struct vty *vty, struct prefix *p, +void route_vty_out_flowspec(struct vty *vty, const struct prefix *p, struct bgp_path_info *path, int display, json_object *json_paths) { diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 71e2b0260..fdffe374c 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) @@ -885,6 +883,27 @@ void bgp_maxmed_update(struct bgp *bgp) } } +int bgp_fsm_error_subcode(int status) +{ + int fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_UNSPECIFIC; + + switch (status) { + case OpenSent: + fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_OPENSENT; + break; + case OpenConfirm: + fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_OPENCONFIRM; + break; + case Established: + fsm_err_subcode = BGP_NOTIFY_FSM_ERR_SUBCODE_ESTABLISHED; + break; + default: + break; + } + + return fsm_err_subcode; +} + /* The maxmed onstartup timer expiry callback. */ static int bgp_maxmed_onstartup_timer(struct thread *thread) { @@ -1455,9 +1474,8 @@ static int bgp_connect_success(struct peer *peer) flog_err_sys(EC_LIB_SOCKET, "%s: bgp_getsockname(): failed for peer %s, fd %d", __func__, peer->host, peer->fd); - bgp_notify_send( - peer, BGP_NOTIFY_FSM_ERR, - BGP_NOTIFY_SUBCODE_UNSPECIFIC); /* internal error */ + bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, + bgp_fsm_error_subcode(peer->status)); bgp_writes_on(peer); return -1; } @@ -1657,7 +1675,8 @@ static int bgp_fsm_event_error(struct peer *peer) flog_err(EC_BGP_FSM, "%s [FSM] unexpected packet received in state %s", peer->host, lookup_msg(bgp_status_msg, peer->status, NULL)); - return bgp_stop_with_notify(peer, BGP_NOTIFY_FSM_ERR, 0); + return bgp_stop_with_notify(peer, BGP_NOTIFY_FSM_ERR, + bgp_fsm_error_subcode(peer->status)); } /* Hold timer expire. This is error of BGP connection. So cut the @@ -1935,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; } @@ -2017,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 @@ -2164,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; @@ -2176,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; @@ -2517,7 +2535,7 @@ int bgp_neighbor_graceful_restart(struct peer *peer, int peer_gr_cmd) peer->peer_gr_present_state = peer_new_state; if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) zlog_debug( - "[BGP_GR] Succesfully change the state of the peer to : %s : !", + "[BGP_GR] Successfully change the state of the peer to : %s : !", print_peer_gr_mode(peer_new_state)); return BGP_GR_SUCCESS; diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h index 6feabbf57..2fd5f6fc4 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,9 @@ 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); /** * Start the route advertisement timer (that honors MRAI) for all the diff --git a/bgpd/bgp_lcommunity.c b/bgpd/bgp_lcommunity.c index 7a4435f6f..c21056f30 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 @@ -178,7 +178,7 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json) int i; int len; char *str_buf; - uint8_t *pnt; + const uint8_t *pnt; uint32_t global, local1, local2; json_object *json_lcommunity_list = NULL; json_object *json_string = NULL; @@ -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 7d63f4d26..e10ab0eef 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 8758d0ca7..3e2ba9802 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 ab0c3a3f1..23c5adbf2 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 af4c0bc04..461e77211 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 81bb45aa7..4a2f7d588 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 0e251dced..10e96497f 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 @@ -1447,7 +1454,7 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size) peer->host, lookup_msg(bgp_status_msg, peer->status, NULL)); bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, - BGP_NOTIFY_SUBCODE_UNSPECIFIC); + bgp_fsm_error_subcode(peer->status)); return BGP_Stop; } @@ -1859,7 +1866,7 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size) peer->host, lookup_msg(bgp_status_msg, peer->status, NULL)); bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, - BGP_NOTIFY_SUBCODE_UNSPECIFIC); + bgp_fsm_error_subcode(peer->status)); return BGP_Stop; } @@ -2251,7 +2258,7 @@ int bgp_capability_receive(struct peer *peer, bgp_size_t size) peer->host, lookup_msg(bgp_status_msg, peer->status, NULL)); bgp_notify_send(peer, BGP_NOTIFY_FSM_ERR, - BGP_NOTIFY_SUBCODE_UNSPECIFIC); + bgp_fsm_error_subcode(peer->status)); return BGP_Stop; } @@ -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_rd.c b/bgpd/bgp_rd.c index be950dfa5..ea9758349 100644 --- a/bgpd/bgp_rd.c +++ b/bgpd/bgp_rd.c @@ -37,7 +37,7 @@ #include "bgpd/rfapi/rfapi_backend.h" #endif -uint16_t decode_rd_type(uint8_t *pnt) +uint16_t decode_rd_type(const uint8_t *pnt) { uint16_t v; @@ -60,7 +60,7 @@ void encode_rd_type(uint16_t v, uint8_t *pnt) } /* type == RD_TYPE_AS */ -void decode_rd_as(uint8_t *pnt, struct rd_as *rd_as) +void decode_rd_as(const uint8_t *pnt, struct rd_as *rd_as) { rd_as->as = (uint16_t)*pnt++ << 8; rd_as->as |= (uint16_t)*pnt++; @@ -68,7 +68,7 @@ void decode_rd_as(uint8_t *pnt, struct rd_as *rd_as) } /* type == RD_TYPE_AS4 */ -void decode_rd_as4(uint8_t *pnt, struct rd_as *rd_as) +void decode_rd_as4(const uint8_t *pnt, struct rd_as *rd_as) { pnt = ptr_get_be32(pnt, &rd_as->as); rd_as->val = ((uint16_t)*pnt++ << 8); diff --git a/bgpd/bgp_rd.h b/bgpd/bgp_rd.h index c5ea34103..da8c553b4 100644 --- a/bgpd/bgp_rd.h +++ b/bgpd/bgp_rd.h @@ -54,11 +54,11 @@ struct rd_vnc_eth { }; #endif -extern uint16_t decode_rd_type(uint8_t *pnt); +extern uint16_t decode_rd_type(const uint8_t *pnt); extern void encode_rd_type(uint16_t, uint8_t *); -extern void decode_rd_as(uint8_t *pnt, struct rd_as *rd_as); -extern void decode_rd_as4(uint8_t *pnt, struct rd_as *rd_as); +extern void decode_rd_as(const uint8_t *pnt, struct rd_as *rd_as); +extern void decode_rd_as4(const uint8_t *pnt, struct rd_as *rd_as); extern void decode_rd_ip(uint8_t *pnt, struct rd_ip *rd_ip); #if ENABLE_BGP_VNC extern void decode_rd_vnc_eth(uint8_t *pnt, struct rd_vnc_eth *rd_vnc_eth); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index c2c034d16..1bd5780a2 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -146,7 +146,7 @@ struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi, } struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi, - safi_t safi, struct prefix *p, + safi_t safi, const struct prefix *p, struct prefix_rd *prd) { struct bgp_node *rn; @@ -1241,7 +1241,8 @@ static enum filter_type bgp_input_filter(struct peer *peer, struct prefix *p, #undef FILTER_EXIST_WARN } -static enum filter_type bgp_output_filter(struct peer *peer, struct prefix *p, +static enum filter_type bgp_output_filter(struct peer *peer, + const struct prefix *p, struct attr *attr, afi_t afi, safi_t safi) { @@ -1282,30 +1283,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 +1317,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 +1544,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, + const struct prefix *p, struct attr *attr) { struct bgp_filter *filter; struct peer *from; @@ -1562,7 +1563,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 +1610,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 +1618,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 +1636,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 +1649,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 +1663,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 +1680,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 +1693,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 +1711,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 +1720,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 +1731,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 +1742,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 +1766,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 +1876,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 +1911,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 +1927,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 +1937,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 +2000,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 +2010,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 +2049,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 +2101,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 +2181,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 +2223,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 +2314,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 +2341,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 +2360,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 +2383,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 +2396,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 +2405,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 { @@ -2486,7 +2489,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, */ if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) { if (BGP_DEBUG(update, UPDATE_OUT)) - zlog_debug("SELECT_DEFER falg set for route %p", rn); + zlog_debug("SELECT_DEFER flag set for route %p", rn); return; } @@ -2682,17 +2685,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 +2947,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 +2971,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 +2995,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 +3012,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 +3022,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 +3034,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 +3203,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 +3250,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 +4609,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 +6022,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 +6034,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, @@ -7326,7 +7343,7 @@ void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type, } /* Static function to display route. */ -static void route_vty_out_route(struct prefix *p, struct vty *vty, +static void route_vty_out_route(const struct prefix *p, struct vty *vty, json_object *json) { int len = 0; @@ -7483,7 +7500,7 @@ static char *bgp_nexthop_hostname(struct peer *peer, struct attr *attr) } /* called from terminal list command */ -void route_vty_out(struct vty *vty, struct prefix *p, +void route_vty_out(struct vty *vty, const struct prefix *p, struct bgp_path_info *path, int display, safi_t safi, json_object *json_paths) { @@ -8079,7 +8096,7 @@ void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr, vty_out(vty, "\n"); } -void route_vty_out_tag(struct vty *vty, struct prefix *p, +void route_vty_out_tag(struct vty *vty, const struct prefix *p, struct bgp_path_info *path, int display, safi_t safi, json_object *json) { @@ -8172,7 +8189,7 @@ void route_vty_out_tag(struct vty *vty, struct prefix *p, } } -void route_vty_out_overlay(struct vty *vty, struct prefix *p, +void route_vty_out_overlay(struct vty *vty, const struct prefix *p, struct bgp_path_info *path, int display, json_object *json_paths) { @@ -12280,7 +12297,7 @@ static int bgp_distance_unset(struct vty *vty, const char *distance_str, } /* Apply BGP information to distance method. */ -uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *pinfo, +uint8_t bgp_distance_apply(const struct prefix *p, struct bgp_path_info *pinfo, afi_t afi, safi_t safi, struct bgp *bgp) { struct bgp_node *rn; diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 0ad656d13..7115f2668 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, @@ -573,8 +590,9 @@ extern void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p, struct bgp_path_info *path, afi_t afi, safi_t safi); -extern uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *path, - afi_t afi, safi_t safi, struct bgp *bgp); +extern uint8_t bgp_distance_apply(const struct prefix *p, + struct bgp_path_info *path, afi_t afi, + safi_t safi, struct bgp *bgp); extern afi_t bgp_node_afi(struct vty *); extern safi_t bgp_node_safi(struct vty *); @@ -584,35 +602,35 @@ extern struct bgp_path_info *info_make(int type, int sub_type, struct peer *peer, struct attr *attr, struct bgp_node *rn); -extern void route_vty_out(struct vty *vty, struct prefix *p, +extern void route_vty_out(struct vty *vty, const struct prefix *p, struct bgp_path_info *path, int display, safi_t safi, json_object *json_paths); -extern void route_vty_out_tag(struct vty *vty, struct prefix *p, +extern void route_vty_out_tag(struct vty *vty, const struct prefix *p, struct bgp_path_info *path, int display, safi_t safi, json_object *json); extern void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr, safi_t safi, bool use_json, json_object *json_ar); -extern void route_vty_out_overlay(struct vty *vty, struct prefix *p, +extern void route_vty_out_overlay(struct vty *vty, const 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, + const 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); /* for encap/vpn */ extern struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi, - safi_t safi, struct prefix *p, + safi_t safi, const struct prefix *p, struct prefix_rd *prd); extern void bgp_path_info_restore(struct bgp_node *rn, struct bgp_path_info *path); @@ -629,8 +647,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 52b540273..029570df3 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 2ca0c7b96..ee1c49666 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 d50716105..5cf0b7398 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 04181d38b..3d74128da 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 69cca9eee..7b468cc03 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 50824cd6d..a29721988 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 fe654bb3e..403ca139f 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 4dc9dfa39..6553211b0 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 fc89881ca..3db9866a9 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. */ @@ -11627,7 +11627,7 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, json_object_object_add( json_neigh, "gracefulRestartInfo", json_grace); } else { - vty_out(vty, " Graceful restart informations:\n"); + vty_out(vty, " Graceful restart information:\n"); if ((p->status == Established) && CHECK_FLAG(p->cap, PEER_CAP_RESTART_RCV)) { @@ -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 f3ab60849..3daef2006 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, const 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,10 +1145,10 @@ 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, +void bgp_zebra_announce(struct bgp_node *rn, const struct prefix *p, struct bgp_path_info *info, struct bgp *bgp, afi_t afi, safi_t safi) { @@ -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 5a02e2fbf..b5b451092 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -32,7 +32,7 @@ extern void bgp_zebra_destroy(void); extern int bgp_zebra_get_table_range(uint32_t chunk_size, uint32_t *start, uint32_t *end); extern int bgp_if_update_all(void); -extern void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, +extern void bgp_zebra_announce(struct bgp_node *rn, const struct prefix *p, struct bgp_path_info *path, struct bgp *bgp, afi_t afi, safi_t safi); extern void bgp_zebra_announce_table(struct bgp *, afi_t, safi_t); @@ -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 267d67e46..945277010 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 1ada056a9..2b67a39ef 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; @@ -1499,6 +1530,12 @@ struct bgp_nlri { #define BGP_NOTIFY_CEASE 6 #define BGP_NOTIFY_CAPABILITY_ERR 7 +/* Subcodes for BGP Finite State Machine Error */ +#define BGP_NOTIFY_FSM_ERR_SUBCODE_UNSPECIFIC 0 +#define BGP_NOTIFY_FSM_ERR_SUBCODE_OPENSENT 1 +#define BGP_NOTIFY_FSM_ERR_SUBCODE_OPENCONFIRM 2 +#define BGP_NOTIFY_FSM_ERR_SUBCODE_ESTABLISHED 3 + #define BGP_NOTIFY_SUBCODE_UNSPECIFIC 0 /* BGP_NOTIFY_HEADER_ERR sub codes. */ @@ -1544,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 @@ -1733,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, @@ -1768,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 *); @@ -1793,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); @@ -1830,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 *); @@ -1842,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); @@ -1900,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/bgpd/rfapi/rfapi_backend.h b/bgpd/rfapi/rfapi_backend.h index 96e464d2a..ae1f7915f 100644 --- a/bgpd/rfapi/rfapi_backend.h +++ b/bgpd/rfapi/rfapi_backend.h @@ -56,7 +56,7 @@ extern void vnc_zebra_withdraw(struct prefix *p, struct bgp_path_info *old_select); -extern void rfapi_vty_out_vncinfo(struct vty *vty, struct prefix *p, +extern void rfapi_vty_out_vncinfo(struct vty *vty, const struct prefix *p, struct bgp_path_info *bpi, safi_t safi); diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c index 2f274015f..5cb4fd5a1 100644 --- a/bgpd/rfapi/rfapi_import.c +++ b/bgpd/rfapi/rfapi_import.c @@ -1040,7 +1040,7 @@ int rfapiEcommunityGetEthernetTag(struct ecommunity *ecom, uint16_t *tag_id) for (i = 0; i < ecom->size; ++i) { as_t as = 0; int encode = 0; - uint8_t *p = ecom->val + (i * ECOMMUNITY_SIZE); + const uint8_t *p = ecom->val + (i * ECOMMUNITY_SIZE); /* High-order octet of type. */ encode = *p++; diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c index 58fdc7c13..b18c9e07b 100644 --- a/bgpd/rfapi/rfapi_vty.c +++ b/bgpd/rfapi/rfapi_vty.c @@ -393,7 +393,7 @@ int rfapiStream2Vty(void *stream, /* input */ } /* called from bgpd/bgp_vty.c'route_vty_out() */ -void rfapi_vty_out_vncinfo(struct vty *vty, struct prefix *p, +void rfapi_vty_out_vncinfo(struct vty *vty, const struct prefix *p, struct bgp_path_info *bpi, safi_t safi) { char *s; diff --git a/bgpd/rfapi/vnc_export_bgp.c b/bgpd/rfapi/vnc_export_bgp.c index 352f5e832..3d34d696b 100644 --- a/bgpd/rfapi/vnc_export_bgp.c +++ b/bgpd/rfapi/vnc_export_bgp.c @@ -1189,7 +1189,7 @@ static void vnc_direct_add_rn_group_rd(struct bgp *bgp, } if (rfg->label > MPLS_LABEL_MAX) { vnc_zlog_debug_verbose( - "%s: VRF \"%s\" is missing defaul label configuration.\n", + "%s: VRF \"%s\" is missing default label configuration.\n", __func__, rfg->name); return; } diff --git a/configure.ac b/configure.ac index fa332b7da..41d1911c3 100755 --- a/configure.ac +++ b/configure.ac @@ -122,7 +122,7 @@ AC_ARG_ENABLE([pkgsrcrcdir], pkgsrcrcdir="$enableval",) dnl XXX add --pkgsrcrcdir to autoconf standard directory list somehow AC_SUBST([pkgsrcrcdir]) -AM_CONDITIONAL([PKGSRC], [test "x$pkgsrcrcdir" != "x"]) +AM_CONDITIONAL([PKGSRC], [test "$pkgsrcrcdir" != ""]) AC_ARG_WITH([moduledir], [AS_HELP_STRING([--with-moduledir=DIR], [module directory (${libdir}/frr/modules)])], [ moduledir="$withval" @@ -197,7 +197,7 @@ AC_DEFUN([AC_C_FLAG], [{ CFLAGS="$ac_c_flag_save" AC_LANG_POP([C]) ]) - if test "${cachename}" = yes; then + if test "$cachename" = "yes"; then m4_if([$3], [], [CFLAGS="$CFLAGS $1"], [$3]) else : @@ -242,8 +242,8 @@ CC="${CC% -std=c99}" AC_C_FLAG([-std=gnu11], [CC="$ac_cc"], [CC="$CC -std=gnu11"]) dnl if the user has specified any CFLAGS, override our settings -if test "x${enable_gcov}" = "xyes"; then - if test "z$orig_cflags" = "z"; then +if test "$enable_gcov" = "yes"; then + if test "$orig_cflags" = ""; then AC_C_FLAG([-coverage]) AC_C_FLAG([-O0]) fi @@ -251,7 +251,7 @@ if test "x${enable_gcov}" = "xyes"; then LDFLAGS="${LDFLAGS} -lgcov" fi -if test "x${enable_clang_coverage}" = "xyes"; then +if test "$enable_clang_coverage" = "yes"; then AC_C_FLAG([-fprofile-instr-generate], [ AC_MSG_ERROR([$CC does not support -fprofile-instr-generate.]) ]) @@ -260,13 +260,13 @@ if test "x${enable_clang_coverage}" = "xyes"; then ]) fi -if test "x${enable_dev_build}" = "xyes"; then +if test "$enable_dev_build" = "yes"; then AC_DEFINE([DEV_BUILD], [1], [Build for development]) - if test "z$orig_cflags" = "z"; then + if test "$orig_cflags" = ""; then AC_C_FLAG([-g3]) AC_C_FLAG([-O0]) fi - if test "x${enable_lua}" = "xyes"; then + if test "$enable_lua" = "yes"; then AX_PROG_LUA([5.3]) AX_LUA_HEADERS AX_LUA_LIBS([ @@ -275,15 +275,15 @@ if test "x${enable_dev_build}" = "xyes"; then ]) fi else - if test "x${enable_lua}" = "xyes"; then + if test "$enable_lua" = "yes"; then AC_MSG_ERROR([Lua is not meant to be built/used outside of development at this time]) fi - if test "z$orig_cflags" = "z"; then + if test "$orig_cflags" = ""; then AC_C_FLAG([-g]) AC_C_FLAG([-O2]) fi fi -AM_CONDITIONAL([DEV_BUILD], [test "x$enable_dev_build" = "xyes"]) +AM_CONDITIONAL([DEV_BUILD], [test "$enable_dev_build" = "yes"]) dnl always want these CFLAGS AC_C_FLAG([-fno-omit-frame-pointer]) @@ -295,7 +295,7 @@ AC_C_FLAG([-Wmissing-declarations]) AC_C_FLAG([-Wpointer-arith]) AC_C_FLAG([-Wbad-function-cast]) AC_C_FLAG([-Wwrite-strings]) -if test x"${enable_gcc_ultra_verbose}" = x"yes" ; then +if test "$enable_gcc_ultra_verbose" = "yes" ; then AC_C_FLAG([-Wcast-qual]) AC_C_FLAG([-Wstrict-prototypes]) AC_C_FLAG([-Wmissing-noreturn]) @@ -318,7 +318,7 @@ dnl for some reason the string consts get 'promoted' to char *, dnl triggering a const to non-const conversion warning. AC_C_FLAG([-diag-disable 3179]) -if test x"${enable_werror}" = x"yes" ; then +if test "$enable_werror" = "yes" ; then WERROR="-Werror" fi AC_SUBST([WERROR]) @@ -369,7 +369,7 @@ AX_PTHREAD([ AC_SEARCH_LIBS([pthread_condattr_setclock], [], [frr_cv_pthread_condattr_setclock=yes], [frr_cv_pthread_condattr_setclock=no]) -if test "$frr_cv_pthread_condattr_setclock" = yes; then +if test "$frr_cv_pthread_condattr_setclock" = "yes"; then AC_DEFINE([HAVE_PTHREAD_CONDATTR_SETCLOCK], [1], [Have pthread.h pthread_condattr_setclock]) fi @@ -400,7 +400,7 @@ if test "$enable_shared" != "yes"; then AC_MSG_ERROR([FRR cannot be built with --disable-shared. If you want statically linked daemons, use --enable-shared --enable-static --enable-static-bin]) fi AC_SUBST([AC_LDFLAGS]) -AM_CONDITIONAL([STATIC_BIN], [test "x$enable_static_bin" = "xyes"]) +AM_CONDITIONAL([STATIC_BIN], [test "$enable_static_bin" = "yes"]) dnl $AR and $RANLIB are set by LT_INIT above AC_MSG_CHECKING([whether $AR supports D option]) @@ -451,7 +451,7 @@ AC_ARG_WITH([pkg-extra-version], ], []) AC_ARG_WITH([pkg-git-version], AS_HELP_STRING([--with-pkg-git-version], [add git information to MOTD and build version string]), - [ test "x$withval" != "xno" && with_pkg_git_version="yes" ]) + [ test "$withval" != "no" && with_pkg_git_version="yes" ]) AC_ARG_WITH([clippy], AS_HELP_STRING([--with-clippy=PATH], [use external clippy helper program])) AC_ARG_WITH([vtysh_pager], @@ -602,23 +602,23 @@ AC_ARG_WITH([crypto], AS_HELP_STRING([--with-crypto=<internal|openssl>], [choose between different implementations of cryptographic functions(default value is --with-crypto=internal)])) #if openssl, else use the internal -AS_IF([test x"${with_crypto}" = x"openssl"], [ +AS_IF([test "$with_crypto" = "openssl"], [ AC_CHECK_LIB([crypto], [EVP_DigestInit], [LIBS="$LIBS -lcrypto"], [], []) -if test $ac_cv_lib_crypto_EVP_DigestInit = no; then +if test "$ac_cv_lib_crypto_EVP_DigestInit" = "no"; then AC_MSG_ERROR([build with openssl has been specified but openssl library was not found on your system]) else AC_DEFINE([CRYPTO_OPENSSL], [1], [Compile with openssl support]) fi -], [test x"${with_crypto}" = x"internal" || test x"${with_crypto}" = x"" ], [AC_DEFINE([CRYPTO_INTERNAL], [1], [Compile with internal cryptographic implementation]) +], [test "$with_crypto" = "internal" || test "$with_crypto" = "" ], [AC_DEFINE([CRYPTO_INTERNAL], [1], [Compile with internal cryptographic implementation]) ], [AC_MSG_ERROR([Unknown value for --with-crypto])] ) -AS_IF([test "${enable_clippy_only}" != "yes"], [ +AS_IF([test "$enable_clippy_only" != "yes"], [ AC_CHECK_HEADERS([json-c/json.h]) AC_CHECK_LIB([json-c], [json_object_get], [LIBS="$LIBS -ljson-c"], [], [-lm]) -if test "$ac_cv_lib_json_c_json_object_get" = no; then +if test "$ac_cv_lib_json_c_json_object_get" = "no"; then AC_CHECK_LIB([json], [json_object_get], [LIBS="$LIBS -ljson"]) - if test "$ac_cv_lib_json_json_object_get" = no; then + if test "$ac_cv_lib_json_json_object_get" = "no"; then AC_MSG_ERROR([libjson is needed to compile]) fi fi @@ -630,8 +630,8 @@ AC_ARG_ENABLE([dev_build], AC_ARG_ENABLE([lua], AS_HELP_STRING([--enable-lua], [Build Lua scripting])) -if test x"${enable_time_check}" != x"no" ; then - if test x"${enable_time_check}" = x"yes" -o x"${enable_time_check}" = x ; then +if test "$enable_time_check" != "no" ; then + if test "$enable_time_check" = "yes" -o "$enable_time_check" = "" ; then AC_DEFINE([CONSUMED_TIME_CHECK], [5000000], [Consumed Time Check]) else AC_DEFINE_UNQUOTED([CONSUMED_TIME_CHECK], [$enable_time_check], [Consumed Time Check]) @@ -650,7 +650,7 @@ case "${enable_systemd}" in "no") ;; "yes") AC_CHECK_LIB([systemd], [sd_notify], [LIBS="$LIBS -lsystemd"]) - if test $ac_cv_lib_systemd_sd_notify = no; then + if test "$ac_cv_lib_systemd_sd_notify" = "no"; then AC_MSG_ERROR([enable systemd has been specified but systemd development env not found on your system]) else AC_DEFINE([HAVE_SYSTEMD], [1], [Compile systemd support in]) @@ -659,11 +659,11 @@ case "${enable_systemd}" in "*") ;; esac -if test "${enable_rr_semantics}" != "no" ; then +if test "$enable_rr_semantics" != "no" ; then AC_DEFINE([HAVE_V6_RR_SEMANTICS], [1], [Compile in v6 Route Replacement Semantics]) fi -if test "${enable_datacenter}" = "yes" ; then +if test "$enable_datacenter" = "yes" ; then AC_DEFINE([HAVE_DATACENTER], [1], [Compile extensions for a DataCenter]) AC_MSG_WARN([The --enable-datacenter compile time option is deprecated. Please modify the init script to pass -F datacenter to the daemons instead.]) DFLT_NAME="datacenter" @@ -671,22 +671,22 @@ else DFLT_NAME="traditional" fi -if test "${enable_fuzzing}" = "yes" ; then +if test "$enable_fuzzing" = "yes" ; then AC_DEFINE([HANDLE_ZAPI_FUZZING], [1], [Compile extensions to use with a fuzzer]) fi -if test "${enable_netlink_fuzzing}" = "yes" ; then +if test "$enable_netlink_fuzzing" = "yes" ; then AC_DEFINE([HANDLE_NETLINK_FUZZING], [1], [Compile extensions to use with a fuzzer for netlink]) fi -if test "${enable_cumulus}" = "yes" ; then +if test "$enable_cumulus" = "yes" ; then AC_DEFINE([HAVE_CUMULUS], [1], [Compile Special Cumulus Code in]) fi AC_SUBST([DFLT_NAME]) AC_DEFINE_UNQUOTED([DFLT_NAME], ["$DFLT_NAME"], [Name of the configuration default set]) -if test "${enable_shell_access}" = "yes"; then +if test "$enable_shell_access" = "yes"; then AC_DEFINE([HAVE_SHELL_ACCESS], [1], [Allow user to use ssh/telnet/bash, be aware this is considered insecure]) fi @@ -702,15 +702,15 @@ AS_IF([test "$host" = "$build"], [ FRR_PYTHON_MODULES([pytest]) -if test "${enable_doc}" != "no"; then +if test "$enable_doc" != "no"; then FRR_PYTHON_MODULES([sphinx], , [ - if test "${enable_doc}" = "yes"; then + if test "$enable_doc" = "yes"; then AC_MSG_ERROR([Documentation was explicitly requested with --enable-doc but sphinx is not available for $PYTHON. Please disable docs or install sphinx.]) fi ]) fi -AM_CONDITIONAL([DOC], [test "${enable_doc}" != "no" -a "$frr_py_mod_sphinx" != "false"]) -AM_CONDITIONAL([DOC_HTML], [test "${enable_doc_html}" = "yes"]) +AM_CONDITIONAL([DOC], [test "$enable_doc" != "no" -a "$frr_py_mod_sphinx" != "false"]) +AM_CONDITIONAL([DOC_HTML], [test "$enable_doc_html" = "yes"]) FRR_PYTHON_MOD_EXEC([sphinx], [--version], [ PYSPHINX="-m sphinx" @@ -731,35 +731,35 @@ fi # AC_MSG_CHECKING([if zebra should be configurable to send Route Advertisements]) -if test "${enable_rtadv}" != "no"; then +if test "$enable_rtadv" != "no"; then AC_MSG_RESULT([yes]) AC_DEFINE([HAVE_RTADV], [1], [Enable IPv6 Routing Advertisement support]) else AC_MSG_RESULT([no]) fi -if test x"${enable_user}" = x"no"; then +if test "$enable_user" = "no"; then enable_user="" else - if test x"${enable_user}" = x"yes" || test x"${enable_user}" = x""; then + if test "$enable_user" = "yes" || test "$enable_user" = ""; then enable_user="frr" fi AC_DEFINE_UNQUOTED([FRR_USER], ["${enable_user}"], [frr User]) fi -if test x"${enable_group}" = x"no"; then +if test "$enable_group" = "no"; then enable_group="" else - if test x"${enable_group}" = x"yes" || test x"${enable_group}" = x""; then + if test "$enable_group" = "yes" || test "$enable_group" = ""; then enable_group="frr" fi AC_DEFINE_UNQUOTED([FRR_GROUP], ["${enable_group}"], [frr Group]) fi -if test x"${enable_vty_group}" = x"yes" ; then +if test "$enable_vty_group" = "yes" ; then AC_MSG_ERROR([--enable-vty-group requires a group as argument, not yes]) -elif test x"${enable_vty_group}" != x""; then - if test x"${enable_vty_group}" != x"no"; then +elif test "$enable_vty_group" != ""; then + if test "$enable_vty_group" != "no"; then AC_DEFINE_UNQUOTED([VTY_GROUP], ["${enable_vty_group}"], [VTY Sockets Group]) fi fi @@ -784,7 +784,7 @@ case "${enable_multipath}" in ;; "") ;; - *) + *) AC_MSG_FAILURE([Please specify digit to enable multipath ARG]) ;; esac @@ -796,12 +796,12 @@ AC_DEFINE_UNQUOTED([VTYSH_PAGER], ["$VTYSH_PAGER"], [What pager to use]) dnl -------------------- dnl Enable code coverage dnl -------------------- -AM_CONDITIONAL([HAVE_GCOV], [test '!' "$enable_gcov" = no]) +AM_CONDITIONAL([HAVE_GCOV], [test "$enable_gcov" != "no"]) dnl ------------------------------------ dnl Alpine only accepts numeric versions dnl ------------------------------------ -if test "x${enable_numeric_version}" != "x" ; then +if test "$enable_numeric_version" != "" ; then VERSION="`echo ${VERSION} | tr -c -d '[[.0-9]]'`" PACKAGE_VERSION="`echo ${PACKAGE_VERSION} | tr -c -d '[[.0-9]]'`" fi @@ -810,7 +810,7 @@ dnl ----------------------------------- dnl Add extra version string to package dnl name, string and version fields. dnl ----------------------------------- -if test "x${EXTRAVERSION}" != "x" ; then +if test "$EXTRAVERSION" != "" ; then VERSION="${VERSION}${EXTRAVERSION}" PACKAGE_VERSION="${PACKAGE_VERSION}${EXTRAVERSION}" AC_SUBST(PACKAGE_EXTRAVERSION, ["${EXTRAVERSION}"]) @@ -818,17 +818,17 @@ if test "x${EXTRAVERSION}" != "x" ; then fi AC_SUBST([EXTRAVERSION]) -if test "x$with_pkg_git_version" = "xyes"; then +if test "$with_pkg_git_version" = "yes"; then if test -d "${srcdir}/.git"; then AC_DEFINE([GIT_VERSION], [1], [include git version info]) else with_pkg_git_version="no" AC_MSG_WARN([--with-pkg-git-version given, but this is not a git checkout]) fi fi -AM_CONDITIONAL([GIT_VERSION], [test "x$with_pkg_git_version" = "xyes"]) +AM_CONDITIONAL([GIT_VERSION], [test "$with_pkg_git_version" = "yes"]) AC_CHECK_TOOL([OBJCOPY], [objcopy], [:]) -if test "x${OBJCOPY}" != "x:"; then +if test "$OBJCOPY" != ":"; then AC_CACHE_CHECK([for .interp value to use], [frr_cv_interp], [ frr_cv_interp="" AC_LINK_IFELSE([AC_LANG_SOURCE([[int main() { return 0; }]])], [ @@ -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 "x${enable_pimd}" != "xno"; 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]) @@ -1141,7 +1131,7 @@ case "$host_os" in AC_DEFINE([BSD_V6_SYSCTL], [1], [BSD v6 sysctl to turn on and off forwarding]) ;; esac -AM_CONDITIONAL([SOLARIS], [test "${SOLARIS}" = "solaris"]) +AM_CONDITIONAL([SOLARIS], [test "$SOLARIS" = "solaris"]) AM_CONDITIONAL([LINUX], [${is_linux}]) AC_SYS_LARGEFILE @@ -1149,7 +1139,7 @@ AC_SYS_LARGEFILE dnl ------------------------ dnl Integrated REALMS option dnl ------------------------ -if test "${enable_realms}" = "yes"; then +if test "$enable_realms" = "yes"; then case "$host_os" in linux*) AC_DEFINE([SUPPORT_REALMS], [1], [Realms support]) @@ -1175,7 +1165,7 @@ AC_CHECK_FUNCS([ \ dnl ########################################################################## dnl LARGE if block spans a lot of "configure"! -if test "${enable_clippy_only}" != "yes"; then +if test "$enable_clippy_only" != "yes"; then dnl ########################################################################## # @@ -1243,15 +1233,15 @@ case "${enable_vtysh}" in LIBS="$prev_libs" AC_CHECK_HEADER([readline/history.h]) - if test $ac_cv_header_readline_history_h = no;then + if test "$ac_cv_header_readline_history_h" = "no"; then AC_MSG_ERROR([readline is too old to have readline/history.h, please update to the latest readline library.]) fi AC_CHECK_LIB([readline], [rl_completion_matches], [true], [], [$LIBREADLINE]) - if test $ac_cv_lib_readline_rl_completion_matches = no; then + if test "$ac_cv_lib_readline_rl_completion_matches" = "no"; then AC_DEFINE([rl_completion_matches], [completion_matches], [Old readline]) fi AC_CHECK_LIB([readline], [append_history], [frr_cv_append_history=yes], [frr_cv_append_history=no], [$LIBREADLINE]) - if test "$frr_cv_append_history" = yes; then + if test "$frr_cv_append_history" = "yes"; then AC_DEFINE([HAVE_APPEND_HISTORY], [1], [Have history.h append_history]) fi ;; @@ -1366,10 +1356,10 @@ case "$host_os" in ISIS_METHOD_MACRO="ISIS_METHOD_DLPI" ;; *) - if test $ac_cv_header_net_bpf_h = no; then - if test $ac_cv_header_sys_dlpi_h = no; then + if test "$ac_cv_header_net_bpf_h" = "no"; then + if test "$ac_cv_header_sys_dlpi_h" = "no"; then AC_MSG_RESULT([none]) - if test "${enable_isisd}" = yes -o "${enable_fabricd}" = yes; then + if test "$enable_isisd" = "yes" -o "$enable_fabricd" = "yes"; then AC_MSG_FAILURE([IS-IS support requested but no packet backend found]) fi AC_MSG_WARN([*** IS-IS support will not be built ***]) @@ -1473,7 +1463,7 @@ AC_CHECK_HEADER([netinet/tcp.h], AC_CHECK_DECLS([TCP_MD5SIG], [], [], MD5_INCLUDES)], [], FRR_INCLUDES) -if test $ac_cv_have_decl_TCP_MD5SIG = no; then +if test "$ac_cv_have_decl_TCP_MD5SIG" = "no"; then AC_CHECK_HEADER([linux/tcp.h], [m4_define([MD5_INCLUDES], FRR_INCLUDES @@ -1490,7 +1480,7 @@ AC_CHECK_LIB([resolv], [res_init]) dnl --------------------------- dnl check system has PCRE regexp dnl --------------------------- -if test "x$enable_pcreposix" = "xyes"; then +if test "$enable_pcreposix" = "yes"; then AC_CHECK_LIB([pcreposix], [regexec], [], [ AC_MSG_ERROR([--enable-pcreposix given but unable to find libpcreposix]) ]) @@ -1498,7 +1488,7 @@ fi AC_SUBST([HAVE_LIBPCREPOSIX]) dnl ########################################################################## -dnl test "${enable_clippy_only}" != "yes" +dnl test "$enable_clippy_only" != "yes" fi dnl END OF LARGE if block dnl ########################################################################## @@ -1547,7 +1537,7 @@ dnl -------------------- dnl Daemon disable check dnl -------------------- -AS_IF([test "${enable_ldpd}" != "no"], [ +AS_IF([test "$enable_ldpd" != "no"], [ AC_DEFINE([HAVE_LDPD], [1], [ldpd]) ]) @@ -1569,7 +1559,7 @@ else esac fi -if test "$ac_cv_lib_json_c_json_object_get" = no -a "x$BFDD" = "xbfdd"; then +if test "$ac_cv_lib_json_c_json_object_get" = "no" -a "$BFDD" = "bfdd"; then AC_MSG_ERROR(["you must use json-c library to use bfdd"]) fi @@ -1580,7 +1570,7 @@ case "$host_os" in no) ;; yes) - if test "${enable_clippy_only}" != "yes"; then + if test "$enable_clippy_only" != "yes"; then if test "$c_ares_found" != "true" ; then AC_MSG_ERROR([nhrpd requires libcares. Please install c-ares and its -dev headers.]) fi @@ -1595,34 +1585,34 @@ case "$host_os" in esac ;; *) - if test "${enable_nhrpd}" = "yes"; then + if test "$enable_nhrpd" = "yes"; then AC_MSG_ERROR([nhrpd requires kernel APIs that are only present on Linux.]) fi ;; esac -if test "${enable_watchfrr}" = "no";then +if test "$enable_watchfrr" = "no";then WATCHFRR="" else WATCHFRR="watchfrr" fi OSPFCLIENT="" -if test "${enable_ospfapi}" != "no";then +if test "$enable_ospfapi" != "no";then AC_DEFINE([SUPPORT_OSPF_API], [1], [OSPFAPI]) - if test "${enable_ospfclient}" != "no";then + if test "$enable_ospfclient" != "no";then OSPFCLIENT="ospfclient" fi fi -if test "${enable_bgp_announce}" = "no";then +if test "$enable_bgp_announce" = "no";then AC_DEFINE([DISABLE_BGP_ANNOUNCE], [1], [Disable BGP installation to zebra]) else AC_DEFINE([DISABLE_BGP_ANNOUNCE], [0], [Disable BGP installation to zebra]) fi -if test "${enable_bgp_vnc}" != "no";then +if test "$enable_bgp_vnc" != "no";then AC_DEFINE([ENABLE_BGP_VNC], [1], [Enable BGP VNC support]) fi @@ -1645,15 +1635,15 @@ esac dnl ########################################################################## dnl LARGE if block -if test "${enable_clippy_only}" != "yes"; then +if test "$enable_clippy_only" != "yes"; then dnl ########################################################################## dnl ------------------ dnl check Net-SNMP library dnl ------------------ -if test "${enable_snmp}" != "" -a "${enable_snmp}" != "no"; then +if test "$enable_snmp" != "" -a "$enable_snmp" != "no"; then AC_PATH_TOOL([NETSNMP_CONFIG], [net-snmp-config], [no]) - if test x"$NETSNMP_CONFIG" = x"no"; then + if test "$NETSNMP_CONFIG" = "no"; then AC_MSG_ERROR([--enable-snmp given but unable to find net-snmp-config]) fi SNMP_LIBS="`${NETSNMP_CONFIG} --agent-libs`" @@ -1726,7 +1716,7 @@ dnl confd dnl --------------- if test "$enable_confd" != "" -a "$enable_confd" != "no"; then AC_CHECK_PROG([CONFD], [confd], [confd], [/bin/false], "${enable_confd}/bin") - if test "x$CONFD" = "x/bin/false"; then + if test "$CONFD" = "/bin/false"; then AC_MSG_ERROR([confd was not found on your system.])] fi CONFD_CFLAGS="-I${enable_confd}/include -L${enable_confd}/lib" @@ -1769,12 +1759,12 @@ fi dnl ------ dnl ZeroMQ dnl ------ -if test "x$enable_zeromq" != "xno"; then +if test "$enable_zeromq" != "no"; then PKG_CHECK_MODULES([ZEROMQ], [libzmq >= 4.0.0], [ AC_DEFINE([HAVE_ZEROMQ], [1], [Enable ZeroMQ support]) ZEROMQ=true ], [ - if test "x$enable_zeromq" = "xyes"; then + if test "$enable_zeromq" = "yes"; then AC_MSG_ERROR([configuration specifies --enable-zeromq but libzmq was not found]) fi ]) @@ -1783,7 +1773,7 @@ fi dnl ------------------------------------ dnl Enable RPKI and add librtr to libs dnl ------------------------------------ -if test "${enable_rpki}" = "yes"; then +if test "$enable_rpki" = "yes"; then PKG_CHECK_MODULES([RTRLIB], [rtrlib >= 0.5.0], [RPKI=true], [RPKI=false @@ -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 ------------------------------------------ @@ -1827,7 +1853,7 @@ AC_CACHE_CHECK([for dlinfo(RTLD_DI_ORIGIN)], [frr_cv_rtld_di_origin], [ frr_cv_rtld_di_origin=no ]) ]) -if test "$frr_cv_rtld_di_origin" = yes; then +if test "$frr_cv_rtld_di_origin" = "yes"; then AC_DEFINE([HAVE_DLINFO_ORIGIN], [1], [Have dlinfo RTLD_DI_ORIGIN]) fi @@ -1847,12 +1873,12 @@ AC_CACHE_CHECK([for dlinfo(RTLD_DI_LINKMAP)], [frr_cv_rtld_di_linkmap], [ frr_cv_rtld_di_linkmap=no ]) ]) -if test "$frr_cv_rtld_di_linkmap" = yes; then +if test "$frr_cv_rtld_di_linkmap" = "yes"; then AC_DEFINE([HAVE_DLINFO_LINKMAP], [1], [Have dlinfo RTLD_DI_LINKMAP]) fi dnl ########################################################################## -dnl test "${enable_clippy_only}" != "yes" +dnl test "$enable_clippy_only" != "yes" fi dnl END OF LARGE if block dnl ########################################################################## @@ -2052,7 +2078,7 @@ fi dnl ------------------- dnl capabilities checks dnl ------------------- -if test "${enable_capabilities}" != "no"; then +if test "$enable_capabilities" != "no"; then AC_MSG_CHECKING([whether prctl PR_SET_KEEPCAPS is available]) AC_TRY_COMPILE([#include <sys/prctl.h>], [prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);], [AC_MSG_RESULT([yes]) @@ -2060,11 +2086,11 @@ if test "${enable_capabilities}" != "no"; then frr_ac_keepcaps="yes"], AC_MSG_RESULT([no]) ) - if test x"${frr_ac_keepcaps}" = x"yes"; then + if test "$frr_ac_keepcaps" = "yes"; then AC_CHECK_HEADERS([sys/capability.h]) fi - if test x"${ac_cv_header_sys_capability_h}" = x"yes"; then - AC_CHECK_LIB([cap], [cap_init], + if test "$ac_cv_header_sys_capability_h" = "yes"; then + AC_CHECK_LIB([cap], [cap_init], [AC_DEFINE([HAVE_LCAPS], [1], [Capabilities]) LIBCAP="-lcap" frr_ac_lcaps="yes"] @@ -2081,14 +2107,14 @@ if test "${enable_capabilities}" != "no"; then ] ) fi - if test x"${frr_ac_scaps}" = x"yes" \ - -o x"${frr_ac_lcaps}" = x"yes"; then + if test "$frr_ac_scaps" = "yes" \ + -o "$frr_ac_lcaps" = "yes"; then AC_DEFINE([HAVE_CAPABILITIES], [1], [capabilities]) fi case "$host_os" in linux*) - if test "${enable_clippy_only}" != "yes"; then + if test "$enable_clippy_only" != "yes"; then if test "$frr_ac_lcaps" != "yes"; then AC_MSG_ERROR([libcap and/or its headers were not found. Running FRR without libcap support built in causes a huge performance penalty.]) fi @@ -2106,8 +2132,8 @@ AC_SUBST([LIBCAP]) dnl --------------------------- dnl check for glibc 'backtrace' -dnl --------------------------- -if test x"${enable_backtrace}" != x"no" ; then +dnl --------------------------- +if test "$enable_backtrace" != "no" ; then backtrace_ok=no PKG_CHECK_MODULES([UNWIND], [libunwind], [ AC_DEFINE([HAVE_LIBUNWIND], [1], [libunwind]) @@ -2134,7 +2160,7 @@ if test x"${enable_backtrace}" != x"no" ; then ]) ;; esac - if test "$backtrace_ok" = no; then + if test "$backtrace_ok" = "no"; then AC_CHECK_HEADER([execinfo.h], [ AC_SEARCH_LIBS([backtrace], [execinfo], [ AC_DEFINE([HAVE_GLIBC_BACKTRACE], [1], [Glibc backtrace]) @@ -2144,7 +2170,7 @@ if test x"${enable_backtrace}" != x"no" ; then fi fi - if test x"${enable_backtrace}" = x"yes" -a x"${backtrace_ok}" = x"no"; then + if test "$enable_backtrace" = "yes" -a "$backtrace_ok" = "no"; then dnl user explicitly requested backtrace but we failed to find support AC_MSG_FAILURE([failed to find backtrace or libunwind support]) fi @@ -2178,7 +2204,7 @@ struct mallinfo ac_x; ac_x = mallinfo (); frr_cv_mallinfo=no ]) ]) -if test "$frr_cv_mallinfo" = yes; then +if test "$frr_cv_mallinfo" = "yes"; then AC_DEFINE([HAVE_MALLINFO], [1], [mallinfo]) fi @@ -2221,7 +2247,7 @@ dnl configure date dnl ---------- dev_version=`echo $VERSION | grep dev` #don't expire deprecated code in non 'dev' branch -if test "${dev_version}" = ""; then +if test "$dev_version" = ""; then CONFDATE=0 else CONFDATE=`date '+%Y%m%d'` @@ -2232,12 +2258,12 @@ dnl ------------------------------ dnl set paths for state directory dnl ------------------------------ AC_MSG_CHECKING([directory to use for state file]) -if test "${prefix}" = "NONE"; then +if test "$prefix" = "NONE"; then frr_statedir_prefix=""; else frr_statedir_prefix=${prefix} fi -if test "${localstatedir}" = '${prefix}/var'; then +if test "$localstatedir" = '${prefix}/var'; then for FRR_STATE_DIR in ${frr_statedir_prefix}/var/run dnl ${frr_statedir_prefix}/var/adm dnl ${frr_statedir_prefix}/etc dnl @@ -2252,7 +2278,7 @@ if test "${localstatedir}" = '${prefix}/var'; then else frr_statedir=${localstatedir} fi -if test $frr_statedir = "/dev/null"; then +if test "$frr_statedir" = "/dev/null"; then AC_MSG_ERROR([STATE DIRECTORY NOT FOUND! FIX OR SPECIFY --localstatedir!]) fi AC_MSG_RESULT([${frr_statedir}]) @@ -2265,8 +2291,8 @@ AC_DEFINE_UNQUOTED([DAEMON_VTY_DIR], ["$frr_statedir%s%s"], [daemon vty director AC_DEFINE_UNQUOTED([DAEMON_DB_DIR], ["$frr_statedir"], [daemon database directory]) dnl autoconf does this, but it does it too late... -test "x$prefix" = xNONE && prefix=$ac_default_prefix -test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' +test "$prefix" = "NONE" && prefix=$ac_default_prefix +test "$exec_prefix" = "NONE" && exec_prefix='${prefix}' dnl get the full path, recursing through variables... vtysh_bin="$bindir/vtysh" @@ -2298,44 +2324,44 @@ AC_DEFINE_UNQUOTED([YANG_MODELS_PATH], ["$CFG_YANGMODELS"], [path to YANG data m AC_DEFINE_UNQUOTED([WATCHFRR_SH_PATH], ["${CFG_SBIN%/}/watchfrr.sh"], [path to watchfrr.sh]) dnl various features -AM_CONDITIONAL([SUPPORT_REALMS], [test "${enable_realms}" = "yes"]) -AM_CONDITIONAL([ENABLE_BGP_VNC], [test x${enable_bgp_vnc} != xno]) +AM_CONDITIONAL([SUPPORT_REALMS], [test "$enable_realms" = "yes"]) +AM_CONDITIONAL([ENABLE_BGP_VNC], [test "$enable_bgp_vnc" != "no"]) AM_CONDITIONAL([BGP_BMP], [$bgpd_bmp]) dnl northbound AM_CONDITIONAL([SQLITE3], [$SQLITE3]) -AM_CONDITIONAL([CONFD], [test "x$enable_confd" != "x"]) -AM_CONDITIONAL([SYSREPO], [test "x$enable_sysrepo" = "xyes"]) -AM_CONDITIONAL([GRPC], [test "x$enable_grpc" = "xyes"]) -AM_CONDITIONAL([ZEROMQ], [test "x$ZEROMQ" = "xtrue"]) +AM_CONDITIONAL([CONFD], [test "$enable_confd" != ""]) +AM_CONDITIONAL([SYSREPO], [test "$enable_sysrepo" = "yes"]) +AM_CONDITIONAL([GRPC], [test "$enable_grpc" = "yes"]) +AM_CONDITIONAL([ZEROMQ], [test "$ZEROMQ" = "true"]) dnl plugins -AM_CONDITIONAL([RPKI], [test "x$RPKI" = "xtrue"]) -AM_CONDITIONAL([SNMP], [test "x$SNMP_METHOD" = "xagentx"]) +AM_CONDITIONAL([RPKI], [test "$RPKI" = "true"]) +AM_CONDITIONAL([SNMP], [test "$SNMP_METHOD" = "agentx"]) AM_CONDITIONAL([IRDP], [$IRDP]) -AM_CONDITIONAL([FPM], [test "x$enable_fpm" = "xyes"]) -AM_CONDITIONAL([HAVE_PROTOBUF], [test "x$enable_protobuf" = "xyes"]) +AM_CONDITIONAL([FPM], [test "$enable_fpm" = "yes"]) +AM_CONDITIONAL([HAVE_PROTOBUF], [test "$enable_protobuf" = "yes"]) AM_CONDITIONAL([HAVE_PROTOBUF3], [$PROTO3]) dnl daemons -AM_CONDITIONAL([VTYSH], [test "x$VTYSH" = "xvtysh"]) -AM_CONDITIONAL([ZEBRA], [test "${enable_zebra}" != "no"]) -AM_CONDITIONAL([BGPD], [test "x${enable_bgpd}" != "no"]) -AM_CONDITIONAL([RIPD], [test "${enable_ripd}" != "no"]) -AM_CONDITIONAL([OSPFD], [test "${enable_ospfd}" != "no"]) -AM_CONDITIONAL([LDPD], [test "${enable_ldpd}" != "no"]) -AM_CONDITIONAL([BFDD], [test "x$BFDD" = "xbfdd"]) -AM_CONDITIONAL([NHRPD], [test "x$NHRPD" = "xnhrpd"]) -AM_CONDITIONAL([EIGRPD], [test "${enable_eigrpd}" != "no"]) -AM_CONDITIONAL([WATCHFRR], [test "x$WATCHFRR" = "xwatchfrr"]) -AM_CONDITIONAL([OSPFCLIENT], [test "x$OSPFCLIENT" = "xospfclient"]) -AM_CONDITIONAL([RIPNGD], [test "${enable_ripngd}" != "no"]) -AM_CONDITIONAL([BABELD], [test "${enable_babeld}" != "no"]) -AM_CONDITIONAL([OSPF6D], [test "${enable_ospf6d}" != "no"]) -AM_CONDITIONAL([ISISD], [test "${enable_isisd}" != "no"]) -AM_CONDITIONAL([PIMD], [test "${enable_pimd}" != "no"]) -AM_CONDITIONAL([PBRD], [test "${enable_pbrd}" != "no"]) -AM_CONDITIONAL([SHARPD], [test "${enable_sharpd}" = "yes"]) -AM_CONDITIONAL([STATICD], [test "${enable_staticd}" != "no"]) -AM_CONDITIONAL([FABRICD], [test "${enable_fabricd}" != "no"]) -AM_CONDITIONAL([VRRPD], [test "${enable_vrrpd}" != "no"]) +AM_CONDITIONAL([VTYSH], [test "$VTYSH" = "vtysh"]) +AM_CONDITIONAL([ZEBRA], [test "$enable_zebra" != "no"]) +AM_CONDITIONAL([BGPD], [test "$enable_bgpd" != "no"]) +AM_CONDITIONAL([RIPD], [test "$enable_ripd" != "no"]) +AM_CONDITIONAL([OSPFD], [test "$enable_ospfd" != "no"]) +AM_CONDITIONAL([LDPD], [test "$enable_ldpd" != "no"]) +AM_CONDITIONAL([BFDD], [test "$BFDD" = "bfdd"]) +AM_CONDITIONAL([NHRPD], [test "$NHRPD" = "nhrpd"]) +AM_CONDITIONAL([EIGRPD], [test "$enable_eigrpd" != "no"]) +AM_CONDITIONAL([WATCHFRR], [test "$WATCHFRR" = "watchfrr"]) +AM_CONDITIONAL([OSPFCLIENT], [test "$OSPFCLIENT" = "ospfclient"]) +AM_CONDITIONAL([RIPNGD], [test "$enable_ripngd" != "no"]) +AM_CONDITIONAL([BABELD], [test "$enable_babeld" != "no"]) +AM_CONDITIONAL([OSPF6D], [test "$enable_ospf6d" != "no"]) +AM_CONDITIONAL([ISISD], [test "$enable_isisd" != "no"]) +AM_CONDITIONAL([PIMD], [test "$enable_pimd" != "no"]) +AM_CONDITIONAL([PBRD], [test "$enable_pbrd" != "no"]) +AM_CONDITIONAL([SHARPD], [test "$enable_sharpd" = "yes"]) +AM_CONDITIONAL([STATICD], [test "$enable_staticd" != "no"]) +AM_CONDITIONAL([FABRICD], [test "$enable_fabricd" != "no"]) +AM_CONDITIONAL([VRRPD], [test "$enable_vrrpd" != "no"]) AC_CONFIG_FILES([Makefile],[sed -e 's/^#AUTODERP# //' -i Makefile]) @@ -2363,7 +2389,7 @@ AC_CONFIG_COMMANDS([lib/route_types.h], [ ${PERL} "${ac_abs_top_srcdir}/lib/route_types.pl" \ < "${ac_abs_top_srcdir}/lib/route_types.txt" \ > "${dst}.tmp" - test -f "${dst}" \ + test -f "$dst" \ && diff "${dst}.tmp" "${dst}" >/dev/null 2>/dev/null \ && rm "${dst}.tmp" \ || mv "${dst}.tmp" "${dst}" @@ -2371,13 +2397,13 @@ AC_CONFIG_COMMANDS([lib/route_types.h], [ PERL="$PERL" ]) -AS_IF([test "x$with_pkg_git_version" = "xyes"], [ +AS_IF([test "$with_pkg_git_version" = "yes"], [ AC_CONFIG_COMMANDS([lib/gitversion.h], [ dst="${ac_abs_top_builddir}/lib/gitversion.h" ${PERL} "${ac_abs_top_srcdir}/lib/gitversion.pl" \ "${ac_abs_top_srcdir}" \ > "${dst}.tmp" - test -f "${dst}" \ + test -f "$dst" \ && diff "${dst}.tmp" "${dst}" >/dev/null 2>/dev/null \ && rm "${dst}.tmp" \ || mv "${dst}.tmp" "${dst}" @@ -2414,9 +2440,9 @@ zebra protobuf enabled : ${enable_protobuf:-no} The above user and group must have read/write access to the state file directory and to the config files in the config file directory." -if test "${enable_doc}" != "no" -a "$frr_py_mod_sphinx" = false; then +if test "$enable_doc" != "no" -a "$frr_py_mod_sphinx" = "false"; then AC_MSG_WARN([sphinx is missing but required to build documentation]) fi -if test "$frr_py_mod_pytest" = false; then +if test "$frr_py_mod_pytest" = "false"; then AC_MSG_WARN([pytest is missing, unit tests cannot be performed]) fi diff --git a/doc/developer/building-frr-for-archlinux.rst b/doc/developer/building-frr-for-archlinux.rst new file mode 100644 index 000000000..7ede35ad9 --- /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 04c6b922c..b730a5ee3 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 859f61231..ef55954ac 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/ldpd.rst b/doc/user/ldpd.rst index 977195d6a..2df4ba300 100644 --- a/doc/user/ldpd.rst +++ b/doc/user/ldpd.rst @@ -108,6 +108,11 @@ LDP Configuration The following command located under MPLS router node configures the MPLS router-id of the local device. +.. index:: [no] ordered-control +.. clicmd:: [no] ordered-control + + Configure LDP Ordered Label Distribution Control. + .. index:: [no] address-family [ipv4 | ipv6] .. clicmd:: [no] address-family [ipv4 | ipv6] diff --git a/doc/user/nhrpd.rst b/doc/user/nhrpd.rst index 95ef9cb7e..8d3bea7c9 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 b72ceb8d3..c9934d1c6 100644 --- a/doc/user/overview.rst +++ b/doc/user/overview.rst @@ -300,10 +300,16 @@ BGP :t:`The Generalized TTL Security Mechanism (GTSM). V. Gill, J. Heasley, D. Meyer, P. Savola, C. Pingnataro. October 2007.` - :rfc:`5575` :t:`Dissemination of Flow Specification Rules. P. Marques, N. Sheth, R. Raszuk, B. Greene, J. Mauch, D. McPherson. August 2009` +- :rfc:`6608` + :t:`Subcodes for BGP Finite State Machine Error. J. Dong, M. Chen, Huawei Technologies, A. Suryanarayana, Cisco Systems. May 2012.` - :rfc:`6810` :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 36c8b44aa..f480c6bdc 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 472e2c53f..f557cbe02 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 111e9dc9e..199685cdf 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 e916a5088..19695e7ab 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 3144b3c28..fc70a344c 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 ea16f4af7..5c15d1d29 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/isisd/isis_misc.c b/isisd/isis_misc.c index 5fa33f550..96b76da92 100644 --- a/isisd/isis_misc.c +++ b/isisd/isis_misc.c @@ -562,20 +562,12 @@ void vty_multiline(struct vty *vty, const char *prefix, const char *format, ...) void vty_out_timestr(struct vty *vty, time_t uptime) { - struct tm tm; time_t difftime = time(NULL); + char buf[MONOTIME_STRLEN]; + difftime -= uptime; - gmtime_r(&difftime, &tm); - - if (difftime < ONE_DAY_SECOND) - vty_out(vty, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min, - tm.tm_sec); - else if (difftime < ONE_WEEK_SECOND) - vty_out(vty, "%dd%02dh%02dm", tm.tm_yday, tm.tm_hour, - tm.tm_min); - else - vty_out(vty, "%02dw%dd%02dh", tm.tm_yday / 7, - tm.tm_yday - ((tm.tm_yday / 7) * 7), tm.tm_hour); - vty_out(vty, " ago"); + frrtime_to_interval(difftime, buf, sizeof(buf)); + + vty_out(vty, "%s ago", buf); } diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index cc22aa5ff..915351262 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -1652,7 +1652,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) if (length != expected_length) { flog_err(EC_ISIS_PACKET, - "Exepected fixed header length = %" PRIu8 + "Expected fixed header length = %" PRIu8 " but got %" PRIu8, expected_length, length); return ISIS_ERROR; diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c index df6280e5c..5b0b70920 100644 --- a/isisd/isis_tlvs.c +++ b/isisd/isis_tlvs.c @@ -2266,7 +2266,7 @@ static int unpack_tlv_spine_leaf(enum isis_tlv_context context, sbuf_push(log, indent, "Unpacking Spine Leaf Extension TLV...\n"); if (tlv_len < 2) { - sbuf_push(log, indent, "WARNING: Unexepected TLV size\n"); + sbuf_push(log, indent, "WARNING: Unexpected TLV size\n"); stream_forward_getp(s, tlv_len); return 0; } @@ -2382,7 +2382,7 @@ static int unpack_tlv_threeway_adj(enum isis_tlv_context context, sbuf_push(log, indent, "Unpacking P2P Three-Way Adjacency TLV...\n"); if (tlv_len != 5 && tlv_len != 15) { - sbuf_push(log, indent, "WARNING: Unexepected TLV size\n"); + sbuf_push(log, indent, "WARNING: Unexpected TLV size\n"); stream_forward_getp(s, tlv_len); return 0; } diff --git a/isisd/isis_vty_fabricd.c b/isisd/isis_vty_fabricd.c index 88f7337a9..09b8d2825 100644 --- a/isisd/isis_vty_fabricd.c +++ b/isisd/isis_vty_fabricd.c @@ -115,6 +115,7 @@ DEFUN (no_triggered_csnp, static void lsp_print_flooding(struct vty *vty, struct isis_lsp *lsp) { char lspid[255]; + char buf[MONOTIME_STRLEN]; lspid_print(lsp->hdr.lsp_id, lspid, true, true); vty_out(vty, "Flooding information for %s\n", lspid); @@ -129,21 +130,10 @@ static void lsp_print_flooding(struct vty *vty, struct isis_lsp *lsp) lsp->flooding_interface : "(null)"); time_t uptime = time(NULL) - lsp->flooding_time; - struct tm tm; - gmtime_r(&uptime, &tm); + frrtime_to_interval(uptime, buf, sizeof(buf)); - if (uptime < ONE_DAY_SECOND) - vty_out(vty, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min, - tm.tm_sec); - else if (uptime < ONE_WEEK_SECOND) - vty_out(vty, "%dd%02dh%02dm", tm.tm_yday, tm.tm_hour, - tm.tm_min); - else - vty_out(vty, "%02dw%dd%02dh", tm.tm_yday / 7, - tm.tm_yday - ((tm.tm_yday / 7) * 7), - tm.tm_hour); - vty_out(vty, " ago)\n"); + vty_out(vty, "%s ago)\n", buf); if (lsp->flooding_circuit_scoped) { vty_out(vty, " Received as circuit-scoped LSP, so not " diff --git a/ldpd/lde.c b/ldpd/lde.c index 5f9403132..64c12e0df 100644 --- a/ldpd/lde.c +++ b/ldpd/lde.c @@ -61,6 +61,8 @@ static void lde_label_list_init(void); static int lde_get_label_chunk(void); static void on_get_label_chunk_response(uint32_t start, uint32_t end); static uint32_t lde_get_next_label(void); +static bool lde_fec_connected(const struct fec_node *); +static bool lde_fec_outside_mpls_network(const struct fec_node *); RB_GENERATE(nbr_tree, lde_nbr, entry, lde_nbr_compare) RB_GENERATE(lde_map_head, lde_map, entry, lde_map_compare) @@ -658,18 +660,31 @@ lde_acl_check(char *acl_name, int af, union ldpd_addr *addr, uint8_t prefixlen) return ldp_acl_request(iev_main_sync, acl_name, af, addr, prefixlen); } +static bool lde_fec_connected(const struct fec_node *fn) +{ + struct fec_nh *fnh; + + LIST_FOREACH(fnh, &fn->nexthops, entry) + if (fnh->flags & F_FEC_NH_CONNECTED) + return true; + + return false; +} + +static bool lde_fec_outside_mpls_network(const struct fec_node *fn) +{ + struct fec_nh *fnh; + + LIST_FOREACH(fnh, &fn->nexthops, entry) + if (!(fnh->flags & F_FEC_NH_NO_LDP)) + return false; + + return true; +} + uint32_t lde_update_label(struct fec_node *fn) { - struct fec_nh *fnh; - int connected = 0; - - LIST_FOREACH(fnh, &fn->nexthops, entry) { - if (fnh->flags & F_FEC_NH_CONNECTED) { - connected = 1; - break; - } - } /* should we allocate a label for this fec? */ switch (fn->fec.type) { @@ -695,7 +710,14 @@ lde_update_label(struct fec_node *fn) break; } - if (connected) { + /* + * If connected interface act as egress for fec. + * If LDP is not configured on an interface but there + * are other NHs with interfaces configured with LDP + * then don't act as an egress for the fec, otherwise + * act as an egress for the fec + */ + if (lde_fec_connected(fn) || lde_fec_outside_mpls_network(fn)) { /* choose implicit or explicit-null depending on configuration */ switch (fn->fec.type) { case FEC_TYPE_IPV4: @@ -735,6 +757,13 @@ lde_send_change_klabel(struct fec_node *fn, struct fec_nh *fnh) struct zapi_pw zpw; struct l2vpn_pw *pw; + /* + * Ordered Control: don't program label into HW until a + * labelmap msg has been received from upstream router + */ + if (fnh->flags & F_FEC_NH_DEFER) + return; + switch (fn->fec.type) { case FEC_TYPE_IPV4: memset(&kr, 0, sizeof(kr)); @@ -901,6 +930,27 @@ lde_send_labelmapping(struct lde_nbr *ln, struct fec_node *fn, int single) struct lde_req *lre; struct map map; struct l2vpn_pw *pw; + struct fec_nh *fnh; + bool allow = false; + + /* + * Ordered Control: do not send a labelmap msg until + * a labelmap message is received from downstream router + * and don't send labelmap back to downstream router + */ + if (ldeconf->flags & F_LDPD_ORDERED_CONTROL) { + LIST_FOREACH(fnh, &fn->nexthops, entry) { + if (fnh->flags & F_FEC_NH_DEFER) + continue; + + if (lde_address_find(ln, fnh->af, &fnh->nexthop)) + return; + allow = true; + break; + } + if (!allow) + return; + } /* * We shouldn't send a new label mapping if we have a pending @@ -1241,6 +1291,7 @@ lde_nbr_del(struct lde_nbr *ln) struct fec_node *fn; struct fec_nh *fnh; struct l2vpn_pw *pw; + struct lde_nbr *lnbr; if (ln == NULL) return; @@ -1256,6 +1307,25 @@ lde_nbr_del(struct lde_nbr *ln) if (!lde_address_find(ln, fnh->af, &fnh->nexthop)) continue; + + /* + * Ordered Control: must mark any non-connected + * NH to wait until we receive a labelmap msg + * before installing in kernel and sending to + * peer, must do this as NHs are not removed + * when lsps go down. Also send label withdraw + * to other neighbors for all fecs from neighbor + * going down + */ + if (ldeconf->flags & F_LDPD_ORDERED_CONTROL) { + fnh->flags |= F_FEC_NH_DEFER; + + RB_FOREACH(lnbr, nbr_tree, &lde_nbrs) { + if (ln->peerid == lnbr->peerid) + continue; + lde_send_labelwithdraw(lnbr, fn, NULL, NULL); + } + } break; case FEC_TYPE_PWID: if (f->u.pwid.lsr_id.s_addr != ln->id.s_addr) diff --git a/ldpd/lde.h b/ldpd/lde.h index ce466c16b..a099f8d28 100644 --- a/ldpd/lde.h +++ b/ldpd/lde.h @@ -114,6 +114,8 @@ struct fec_nh { }; #define F_FEC_NH_NEW 0x01 #define F_FEC_NH_CONNECTED 0x02 +#define F_FEC_NH_DEFER 0x04 /* running ordered control */ +#define F_FEC_NH_NO_LDP 0x08 /* no ldp on this interface */ struct fec_node { struct fec fec; diff --git a/ldpd/lde_lib.c b/ldpd/lde_lib.c index eb1a6d943..8f524e0aa 100644 --- a/ldpd/lde_lib.c +++ b/ldpd/lde_lib.c @@ -20,6 +20,7 @@ #include <zebra.h> #include "ldpd.h" +#include "ldpe.h" #include "lde.h" #include "log.h" @@ -325,6 +326,7 @@ lde_kernel_insert(struct fec *fec, int af, union ldpd_addr *nexthop, { struct fec_node *fn; struct fec_nh *fnh; + struct iface *iface; fn = (struct fec_node *)fec_find(&ft, fec); if (fn == NULL) @@ -333,9 +335,21 @@ lde_kernel_insert(struct fec *fec, int af, union ldpd_addr *nexthop, fn->data = data; fnh = fec_nh_find(fn, af, nexthop, ifindex, route_type, route_instance); - if (fnh == NULL) + if (fnh == NULL) { fnh = fec_nh_add(fn, af, nexthop, ifindex, route_type, route_instance); + /* + * Ordered Control: if not a connected route and not a route + * learned over an interface not running LDP and not a PW + * then mark to wait until we receive labelmap msg before + * installing in kernel and sending to peer + */ + iface = if_lookup(ldeconf, ifindex); + if ((ldeconf->flags & F_LDPD_ORDERED_CONTROL) && + !connected && iface != NULL && fec->type != FEC_TYPE_PWID) + fnh->flags |= F_FEC_NH_DEFER; + } + fnh->flags |= F_FEC_NH_NEW; if (connected) fnh->flags |= F_FEC_NH_CONNECTED; @@ -374,15 +388,25 @@ lde_kernel_update(struct fec *fec) struct fec_nh *fnh, *safe; struct lde_nbr *ln; struct lde_map *me; + struct iface *iface; fn = (struct fec_node *)fec_find(&ft, fec); if (fn == NULL) return; LIST_FOREACH_SAFE(fnh, &fn->nexthops, entry, safe) { - if (fnh->flags & F_FEC_NH_NEW) + if (fnh->flags & F_FEC_NH_NEW) { fnh->flags &= ~F_FEC_NH_NEW; - else { + /* + * if LDP configured on interface or a static route + * clear flag else treat fec as a connected route + */ + iface = if_lookup(ldeconf,fnh->ifindex); + if (iface || fnh->route_type == ZEBRA_ROUTE_STATIC) + fnh->flags &=~F_FEC_NH_NO_LDP; + else + fnh->flags |= F_FEC_NH_NO_LDP; + } else { lde_send_delete_klabel(fn, fnh); fec_nh_del(fnh); } @@ -445,6 +469,7 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln) struct lde_req *lre; struct lde_map *me; struct l2vpn_pw *pw; + bool send_map = false; lde_map2fec(map, ln->id, &fec); @@ -525,6 +550,15 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln) if (!lde_address_find(ln, fnh->af, &fnh->nexthop)) continue; + /* + * Ordered Control: labelmap msg received from + * NH so clear flag and send labelmap msg to + * peer + */ + if (ldeconf->flags & F_LDPD_ORDERED_CONTROL) { + send_map = true; + fnh->flags &= ~F_FEC_NH_DEFER; + } fnh->remote_label = map->label; lde_send_change_klabel(fn, fnh); break; @@ -558,6 +592,15 @@ lde_check_mapping(struct map *map, struct lde_nbr *ln) * loop detection. LMp.28 - LMp.30 are unnecessary because we are * merging capable. */ + + /* + * Ordered Control: just received a labelmap for this fec from NH so + * need to send labelmap to all peers + * LMp.20 - LMp21 Execute procedure to send Label Mapping + */ + if (send_map && fn->local_label != NO_LABEL) + RB_FOREACH(ln, nbr_tree, &lde_nbrs) + lde_send_labelmapping(ln, fn, 1); } void @@ -757,6 +800,7 @@ lde_check_withdraw(struct map *map, struct lde_nbr *ln) struct fec_nh *fnh; struct lde_map *me; struct l2vpn_pw *pw; + struct lde_nbr *lnbr; /* wildcard label withdraw */ if (map->type == MAP_TYPE_WILDCARD || @@ -803,6 +847,26 @@ lde_check_withdraw(struct map *map, struct lde_nbr *ln) if (me && (map->label == NO_LABEL || map->label == me->map.label)) /* LWd.4: remove record of previously received lbl mapping */ lde_map_del(ln, me, 0); + + /* Ordered Control: additional withdraw steps */ + if (ldeconf->flags & F_LDPD_ORDERED_CONTROL) { + /* LWd.8: for each neighbor other that src of withdraw msg */ + RB_FOREACH(lnbr, nbr_tree, &lde_nbrs) { + if (ln->peerid == lnbr->peerid) + continue; + + /* LWd.9: check if previously sent a label mapping */ + me = (struct lde_map *)fec_find(&lnbr->sent_map, + &fn->fec); + /* + * LWd.10: does label sent to peer "map" to withdraw + * label + */ + if (me) + /* LWd.11: send label withdraw */ + lde_send_labelwithdraw(lnbr, fn, NULL, NULL); + } + } } void @@ -813,6 +877,7 @@ lde_check_withdraw_wcard(struct map *map, struct lde_nbr *ln) struct fec_nh *fnh; struct lde_map *me; struct l2vpn_pw *pw; + struct lde_nbr *lnbr; /* LWd.2: send label release */ lde_send_labelrelease(ln, NULL, map, map->label); @@ -859,6 +924,26 @@ lde_check_withdraw_wcard(struct map *map, struct lde_nbr *ln) * label mapping */ lde_map_del(ln, me, 0); + + /* Ordered Control: additional withdraw steps */ + if (ldeconf->flags & F_LDPD_ORDERED_CONTROL) { + /* LWd.8: for each neighbor other that src of withdraw msg */ + RB_FOREACH(lnbr, nbr_tree, &lde_nbrs) { + if (ln->peerid == lnbr->peerid) + continue; + + /* LWd.9: check if previously sent a label mapping */ + me = (struct lde_map *)fec_find(&lnbr->sent_map, + &fn->fec); + /* + * LWd.10: does label sent to peer "map" to withdraw + * label + */ + if (me) + /* LWd.11: send label withdraw */ + lde_send_labelwithdraw(lnbr, fn, NULL, NULL); + } + } } } diff --git a/ldpd/ldp_vty.h b/ldpd/ldp_vty.h index 5e9df4aaf..af5f1d561 100644 --- a/ldpd/ldp_vty.h +++ b/ldpd/ldp_vty.h @@ -52,6 +52,7 @@ int ldp_vty_label_expnull(struct vty *, const char *, const char *); int ldp_vty_label_accept(struct vty *, const char *, const char *, const char *); int ldp_vty_ttl_security(struct vty *, const char *); int ldp_vty_router_id(struct vty *, const char *, struct in_addr); +int ldp_vty_ordered_control(struct vty *, const char *); int ldp_vty_ds_cisco_interop(struct vty *, const char *); int ldp_vty_trans_pref_ipv4(struct vty *, const char *); int ldp_vty_neighbor_password(struct vty *, const char *, struct in_addr, const char *); diff --git a/ldpd/ldp_vty_cmds.c b/ldpd/ldp_vty_cmds.c index c24e1917c..c10c6ae35 100644 --- a/ldpd/ldp_vty_cmds.c +++ b/ldpd/ldp_vty_cmds.c @@ -221,6 +221,15 @@ DEFPY (ldp_router_id, return (ldp_vty_router_id(vty, no, address)); } +DEFPY (ldp_ordered_control, + ldp_ordered_control_cmd, + "[no] ordered-control", + NO_STR + "Configure LDP ordered label distribution control mode\n") +{ + return (ldp_vty_ordered_control(vty, no)); +} + DEFPY (ldp_discovery_targeted_hello_accept, ldp_discovery_targeted_hello_accept_cmd, "[no] discovery targeted-hello accept [from <(1-199)|(1300-2699)|WORD>$from_acl]", @@ -807,6 +816,7 @@ ldp_vty_init (void) install_element(LDP_NODE, &ldp_neighbor_session_holdtime_cmd); install_element(LDP_NODE, &ldp_neighbor_ttl_security_cmd); install_element(LDP_NODE, &ldp_router_id_cmd); + install_element(LDP_NODE, &ldp_ordered_control_cmd); install_element(LDP_IPV4_NODE, &ldp_discovery_link_holdtime_cmd); install_element(LDP_IPV4_NODE, &ldp_discovery_targeted_holdtime_cmd); diff --git a/ldpd/ldp_vty_conf.c b/ldpd/ldp_vty_conf.c index 816fcc64b..05b896256 100644 --- a/ldpd/ldp_vty_conf.c +++ b/ldpd/ldp_vty_conf.c @@ -278,6 +278,9 @@ ldp_config_write(struct vty *vty) if (ldpd_conf->flags & F_LDPD_DS_CISCO_INTEROP) vty_out (vty, " dual-stack cisco-interop\n"); + if (ldpd_conf->flags & F_LDPD_ORDERED_CONTROL) + vty_out (vty, " ordered-control\n"); + RB_FOREACH(nbrp, nbrp_head, &ldpd_conf->nbrp_tree) { if (nbrp->flags & F_NBRP_KEEPALIVE) vty_out (vty, " neighbor %s session holdtime %u\n", @@ -997,6 +1000,19 @@ ldp_vty_router_id(struct vty *vty, const char *negate, struct in_addr address) } int +ldp_vty_ordered_control(struct vty *vty, const char *negate) +{ + if (negate) + vty_conf->flags &= ~F_LDPD_ORDERED_CONTROL; + else + vty_conf->flags |= F_LDPD_ORDERED_CONTROL; + + ldp_config_apply(vty, vty_conf); + + return (CMD_SUCCESS); +} + +int ldp_vty_ds_cisco_interop(struct vty *vty, const char * negate) { if (negate) diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c index 78b1c3e54..0f9f055d0 100644 --- a/ldpd/ldpd.c +++ b/ldpd/ldpd.c @@ -1285,6 +1285,14 @@ merge_global(struct ldpd_conf *conf, struct ldpd_conf *xconf) conf->rtr_id = xconf->rtr_id; } + /* + * Configuration of ordered-control or independent-control + * requires resetting all neighborships. + */ + if ((conf->flags & F_LDPD_ORDERED_CONTROL) != + (xconf->flags & F_LDPD_ORDERED_CONTROL)) + ldpe_reset_nbrs(AF_UNSPEC); + conf->lhello_holdtime = xconf->lhello_holdtime; conf->lhello_interval = xconf->lhello_interval; conf->thello_holdtime = xconf->thello_holdtime; diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h index 006780f03..a736b4ca3 100644 --- a/ldpd/ldpd.h +++ b/ldpd/ldpd.h @@ -511,6 +511,8 @@ DECLARE_QOBJ_TYPE(ldpd_conf) #define F_LDPD_NO_FIB_UPDATE 0x0001 #define F_LDPD_DS_CISCO_INTEROP 0x0002 #define F_LDPD_ENABLED 0x0004 +#define F_LDPD_ORDERED_CONTROL 0x0008 + struct ldpd_af_global { struct thread *disc_ev; diff --git a/lib/agg_table.h b/lib/agg_table.h index 40ffe8c75..f95fed675 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 787da08e2..9c927ca4a 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 f964c9e2a..9d91ea915 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 44ea19b55..e4e05faa4 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 733dd41ea..653fbe8fe 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/monotime.h b/lib/monotime.h index e246f177d..dda763784 100644 --- a/lib/monotime.h +++ b/lib/monotime.h @@ -112,6 +112,26 @@ static inline char *time_to_string(time_t ts, char *buf) return ctime_r(&tbuf, buf); } +/* Convert interval to human-friendly string, used in cli output e.g. */ +static inline const char *frrtime_to_interval(time_t t, char *buf, + size_t buflen) +{ + struct tm tm; + + gmtime_r(&t, &tm); + + if (t < ONE_DAY_SECOND) + snprintf(buf, buflen, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min, + tm.tm_sec); + else if (t < ONE_WEEK_SECOND) + snprintf(buf, buflen, "%dd%02dh%02dm", tm.tm_yday, tm.tm_hour, + tm.tm_min); + else + snprintf(buf, buflen, "%02dw%dd%02dh", tm.tm_yday / 7, + tm.tm_yday - ((tm.tm_yday / 7) * 7), tm.tm_hour); + return buf; +} + #ifdef __cplusplus } #endif diff --git a/lib/ntop.c b/lib/ntop.c index 066e10e3e..ccbf8793d 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/lib/prefix.h b/lib/prefix.h index b01f7d1fd..51b3dacb8 100644 --- a/lib/prefix.h +++ b/lib/prefix.h @@ -531,7 +531,7 @@ static inline int is_host_route(struct prefix *p) return 0; } -static inline int is_default_host_route(struct prefix *p) +static inline int is_default_host_route(const struct prefix *p) { if (p->family == AF_INET) { return (p->u.prefix4.s_addr == INADDR_ANY && diff --git a/lib/stream.h b/lib/stream.h index 36c65afa3..425f0c5ed 100644 --- a/lib/stream.h +++ b/lib/stream.h @@ -354,9 +354,10 @@ extern void stream_fifo_free(struct stream_fifo *fifo); * bit), for 64-bit values (you need to cast them anyway), and neither for * encoding (because it's downcasted.) */ -static inline uint8_t *ptr_get_be32(uint8_t *ptr, uint32_t *out) +static inline const uint8_t *ptr_get_be32(const uint8_t *ptr, uint32_t *out) { uint32_t tmp; + memcpy(&tmp, ptr, sizeof(tmp)); *out = ntohl(tmp); return ptr + 4; diff --git a/lib/zclient.c b/lib/zclient.c index eac6c7081..93c5fe39a 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -690,8 +690,9 @@ static int zclient_connect(struct thread *t) return zclient_start(zclient); } -int zclient_send_rnh(struct zclient *zclient, int command, struct prefix *p, - bool exact_match, vrf_id_t vrf_id) +int zclient_send_rnh(struct zclient *zclient, int command, + const struct prefix *p, bool exact_match, + vrf_id_t vrf_id) { struct stream *s; diff --git a/lib/zclient.h b/lib/zclient.h index e6f4c747e..f18511dc8 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -738,7 +738,7 @@ extern void zebra_read_pw_status_update(ZAPI_CALLBACK_ARGS, struct zapi_pw_statu extern int zclient_route_send(uint8_t, struct zclient *, struct zapi_route *); extern int zclient_send_rnh(struct zclient *zclient, int command, - struct prefix *p, bool exact_match, + const struct prefix *p, bool exact_match, vrf_id_t vrf_id); int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh, uint32_t api_flags); diff --git a/m4/ax_python.m4 b/m4/ax_python.m4 index 69809184e..d293da525 100644 --- a/m4/ax_python.m4 +++ b/m4/ax_python.m4 @@ -3,7 +3,7 @@ dnl 2019 David Lamparter for NetDEF, Inc. dnl SPDX-License-Identifier: GPL-2.0-or-later dnl the _ at the beginning will be cut off (to support the empty version string) -m4_define_default([_FRR_PY_VERS], [_3 _ _2 _3.7 _3.6 _3.5 _3.4 _3.3 _3.2 _2.7]) +m4_define_default([_FRR_PY_VERS], [_3 _ _2 _3.8 _3.7 _3.6 _3.5 _3.4 _3.3 _3.2 _2.7]) dnl check basic interpreter properties (py2/py3) dnl doubles as simple check whether the interpreter actually works diff --git a/nhrpd/netlink_arp.c b/nhrpd/netlink_arp.c index 8fd8280c5..cf338a087 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 81f7d9942..42f6a88f9 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 5ca477fb5..2dc019ce6 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 2552f9fd1..1c2b2b28f 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 f6d18fb77..a3066f917 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/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c index 1717f1e65..f8df37094 100644 --- a/ospf6d/ospf6_zebra.c +++ b/ospf6d/ospf6_zebra.c @@ -256,7 +256,7 @@ static void ospf6_zebra_route_update(int type, struct ospf6_route *request) && ospf6_route_is_same(request, request->next)) { if (IS_OSPF6_DEBUG_ZEBRA(SEND)) zlog_debug( - " Best-path removal resulted Sencondary addition"); + " Best-path removal resulted Secondary addition"); type = ADD; request = request->next; } diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index 58f087ca4..9cd83c245 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -731,7 +731,7 @@ static void nsm_change_state(struct ospf_neighbor *nbr, int state) OSPF_DD_FLAG_I | OSPF_DD_FLAG_M | OSPF_DD_FLAG_MS; if (CHECK_FLAG(oi->ospf->config, OSPF_LOG_ADJACENCY_DETAIL)) zlog_info( - "%s: Intializing [DD]: %s with seqnum:%x , flags:%x", + "%s: Initializing [DD]: %s with seqnum:%x , flags:%x", (oi->ospf->name) ? oi->ospf->name : VRF_DEFAULT_NAME, inet_ntoa(nbr->router_id), nbr->dd_seqnum, diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index d87f02627..0808f245e 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 abc154896..30208deb1 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(); @@ -3732,8 +3739,6 @@ static void pim_show_bsr(struct pim_instance *pim, char bsr_str[PREFIX_STRLEN]; json_object *json = NULL; - vty_out(vty, "PIMv2 Bootstrap information\n"); - if (pim->global_scope.current_bsr.s_addr == INADDR_ANY) { strlcpy(bsr_str, "0.0.0.0", sizeof(bsr_str)); pim_time_uptime(uptime, sizeof(uptime), @@ -3779,6 +3784,7 @@ static void pim_show_bsr(struct pim_instance *pim, } else { + vty_out(vty, "PIMv2 Bootstrap information\n"); vty_out(vty, "Current preferred BSR address: %s\n", bsr_str); vty_out(vty, "Priority Fragment-Tag State UpTime\n"); @@ -5790,13 +5796,18 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, int oif_vif_index; struct interface *ifp_in; char proto[100]; + char state_str[PIM_REG_STATE_STR_LEN]; char mroute_uptime[10]; if (uj) { json = json_object_new_object(); } else { + vty_out(vty, "IP Multicast Routing Table\n"); + vty_out(vty, "Flags: S- Sparse, C - Connected, P - Pruned\n"); + vty_out(vty, + " R - RP-bit set, F - Register flag, T - SPT-bit set\n"); vty_out(vty, - "Source Group Proto Input Output TTL Uptime\n"); + "\nSource Group Flags Proto Input Output TTL Uptime\n"); } now = pim_time_monotonic_sec(); @@ -5819,6 +5830,23 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, sizeof(grp_str)); pim_inet4_dump("<source?>", c_oil->oil.mfcc_origin, src_str, sizeof(src_str)); + + strlcpy(state_str, "S", sizeof(state_str)); + /* When a non DR receives a igmp join, it creates a (*,G) + * channel_oil without any upstream creation */ + if (c_oil->up) { + if (PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(c_oil->up->flags)) + strlcat(state_str, "C", sizeof(state_str)); + if (pim_upstream_is_sg_rpt(c_oil->up)) + strlcat(state_str, "R", sizeof(state_str)); + if (PIM_UPSTREAM_FLAG_TEST_FHR(c_oil->up->flags)) + strlcat(state_str, "F", sizeof(state_str)); + if (c_oil->up->sptbit == PIM_UPSTREAM_SPTBIT_TRUE) + strlcat(state_str, "T", sizeof(state_str)); + } + if (pim_channel_oil_empty(c_oil)) + strlcat(state_str, "P", sizeof(state_str)); + ifp_in = pim_if_find_by_vif_index(pim, c_oil->oil.mfcc_parent); if (ifp_in) @@ -5842,7 +5870,8 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, } /* Find the source nested under the group, create it if - * it doesn't exist */ + * it doesn't exist + */ json_object_object_get_ex(json_group, src_str, &json_source); @@ -5965,14 +5994,16 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, } vty_out(vty, - "%-15s %-15s %-6s %-16s %-16s %-3d %8s\n", - src_str, grp_str, proto, in_ifname, - out_ifname, ttl, mroute_uptime); + "%-15s %-15s %-15s %-6s %-16s %-16s %-3d %8s\n", + src_str, grp_str, state_str, proto, + in_ifname, out_ifname, ttl, + mroute_uptime); if (first) { src_str[0] = '\0'; grp_str[0] = '\0'; in_ifname[0] = '\0'; + state_str[0] = '\0'; mroute_uptime[0] = '\0'; first = 0; } @@ -5980,9 +6011,10 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty, } if (!uj && !found_oif) { - vty_out(vty, "%-15s %-15s %-6s %-16s %-16s %-3d %8s\n", - src_str, grp_str, "none", in_ifname, "none", 0, - "--:--:--"); + vty_out(vty, + "%-15s %-15s %-15s %-6s %-16s %-16s %-3d %8s\n", + src_str, grp_str, state_str, "none", in_ifname, + "none", 0, "--:--:--"); } } @@ -6600,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; } @@ -6672,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)", @@ -7237,11 +7289,20 @@ DEFUN (no_ip_pim_ecmp_rebalance, static int pim_cmd_igmp_start(struct vty *vty, struct interface *ifp) { struct pim_interface *pim_ifp; + struct pim_instance *pim; uint8_t need_startup = 0; pim_ifp = ifp->info; if (!pim_ifp) { + pim = pim_get_pim_instance(ifp->vrf_id); + /* Limit mcast interfaces to number of vifs available */ + if (pim->mcast_if_count == MAXVIFS) { + vty_out(vty, + "Max multicast interfaces(%d) Reached. Could not enable IGMP on interface %s\n", + MAXVIFS, ifp->name); + return CMD_WARNING_CONFIG_FAILED; + } (void)pim_if_new(ifp, true, false, false, false); need_startup = 1; } else { @@ -7991,13 +8052,21 @@ DEFPY_HIDDEN (interface_ip_igmp_query_generate, return CMD_SUCCESS; } -static int pim_cmd_interface_add(struct interface *ifp) +static int pim_cmd_interface_add(struct vty *vty, struct interface *ifp) { struct pim_interface *pim_ifp = ifp->info; + struct pim_instance *pim; - if (!pim_ifp) + if (!pim_ifp) { + pim = pim_get_pim_instance(ifp->vrf_id); + /* Limiting mcast interfaces to number of VIFs */ + if (pim->mcast_if_count == MAXVIFS) { + vty_out(vty, "Max multicast interfaces(%d) reached.", + MAXVIFS); + return 0; + } pim_ifp = pim_if_new(ifp, false, true, false, false); - else + } else PIM_IF_DO_PIM(pim_ifp->options); pim_if_addr_add_all(ifp); @@ -8068,15 +8137,17 @@ DEFPY (interface_ip_pim_activeactive, VTY_DECLVAR_CONTEXT(interface, ifp); struct pim_interface *pim_ifp; - if (!no && !pim_cmd_interface_add(ifp)) { - vty_out(vty, "Could not enable PIM SM active-active on interface\n"); + if (!no && !pim_cmd_interface_add(vty, ifp)) { + vty_out(vty, + "Could not enable PIM SM active-active on interface %s\n", + ifp->name); return CMD_WARNING_CONFIG_FAILED; } - if (PIM_DEBUG_MLAG) - zlog_debug("%sConfiguring PIM active-active on Interface: %s", - no ? "Un-":" ", ifp->name); + if (PIM_DEBUG_MLAG) + zlog_debug("%sConfiguring PIM active-active on Interface: %s", + no ? "Un-" : " ", ifp->name); pim_ifp = ifp->info; if (no) @@ -8096,8 +8167,9 @@ DEFUN_HIDDEN (interface_ip_pim_ssm, { VTY_DECLVAR_CONTEXT(interface, ifp); - if (!pim_cmd_interface_add(ifp)) { - vty_out(vty, "Could not enable PIM SM on interface\n"); + if (!pim_cmd_interface_add(vty, ifp)) { + vty_out(vty, "Could not enable PIM SM on interface %s\n", + ifp->name); return CMD_WARNING_CONFIG_FAILED; } @@ -8113,8 +8185,9 @@ static int interface_ip_pim_helper(struct vty *vty) VTY_DECLVAR_CONTEXT(interface, ifp); - if (!pim_cmd_interface_add(ifp)) { - vty_out(vty, "Could not enable PIM SM on interface\n"); + if (!pim_cmd_interface_add(vty, ifp)) { + vty_out(vty, "Could not enable PIM SM on interface %s\n", + ifp->name); return CMD_WARNING_CONFIG_FAILED; } @@ -8402,8 +8475,10 @@ DEFUN (interface_ip_pim_hello, struct pim_interface *pim_ifp = ifp->info; if (!pim_ifp) { - if (!pim_cmd_interface_add(ifp)) { - vty_out(vty, "Could not enable PIM SM on interface\n"); + if (!pim_cmd_interface_add(vty, ifp)) { + vty_out(vty, + "Could not enable PIM SM on interface %s\n", + ifp->name); return CMD_WARNING_CONFIG_FAILED; } } @@ -9145,8 +9220,10 @@ DEFUN (ip_pim_bfd, struct bfd_info *bfd_info = NULL; if (!pim_ifp) { - if (!pim_cmd_interface_add(ifp)) { - vty_out(vty, "Could not enable PIM SM on interface\n"); + if (!pim_cmd_interface_add(vty, ifp)) { + vty_out(vty, + "Could not enable PIM SM on interface %s\n", + ifp->name); return CMD_WARNING; } } @@ -9196,8 +9273,10 @@ DEFUN (ip_pim_bsm, struct pim_interface *pim_ifp = ifp->info; if (!pim_ifp) { - if (!pim_cmd_interface_add(ifp)) { - vty_out(vty, "Could not enable PIM SM on interface\n"); + if (!pim_cmd_interface_add(vty, ifp)) { + vty_out(vty, + "Could not enable PIM SM on interface %s\n", + ifp->name); return CMD_WARNING; } } @@ -9240,8 +9319,10 @@ DEFUN (ip_pim_ucast_bsm, struct pim_interface *pim_ifp = ifp->info; if (!pim_ifp) { - if (!pim_cmd_interface_add(ifp)) { - vty_out(vty, "Could not enable PIM SM on interface\n"); + if (!pim_cmd_interface_add(vty, ifp)) { + vty_out(vty, + "Could not enable PIM SM on interface %s\n", + ifp->name); return CMD_WARNING; } } @@ -9308,8 +9389,10 @@ DEFUN( struct pim_interface *pim_ifp = ifp->info; if (!pim_ifp) { - if (!pim_cmd_interface_add(ifp)) { - vty_out(vty, "Could not enable PIM SM on interface\n"); + if (!pim_cmd_interface_add(vty, ifp)) { + vty_out(vty, + "Could not enable PIM SM on interface %s\n", + ifp->name); return CMD_WARNING; } } @@ -10770,6 +10853,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_iface.c b/pimd/pim_iface.c index cb31878e0..d05790d33 100644 --- a/pimd/pim_iface.c +++ b/pimd/pim_iface.c @@ -186,6 +186,7 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim, pim_sock_reset(ifp); pim_if_add_vif(ifp, ispimreg, is_vxlan_term); + pim_ifp->pim->mcast_if_count++; return pim_ifp; } @@ -209,6 +210,7 @@ void pim_if_delete(struct interface *ifp) pim_neighbor_delete_all(ifp, "Interface removed from configuration"); pim_if_del_vif(ifp); + pim_ifp->pim->mcast_if_count--; list_delete(&pim_ifp->igmp_socket_list); list_delete(&pim_ifp->pim_neighbor_list); @@ -1583,8 +1585,14 @@ int pim_ifp_create(struct interface *ifp) } if (!strncmp(ifp->name, PIM_VXLAN_TERM_DEV_NAME, - sizeof(PIM_VXLAN_TERM_DEV_NAME))) - pim_vxlan_add_term_dev(pim, ifp); + sizeof(PIM_VXLAN_TERM_DEV_NAME))) { + if (pim->mcast_if_count < MAXVIFS) + pim_vxlan_add_term_dev(pim, ifp); + else + zlog_warn( + "%s: Cannot enable pim on %s. MAXVIFS(%d) reached. Deleting and readding the vxlan termimation device after unconfiguring pim from other interfaces may succeed.", + __func__, ifp->name, MAXVIFS); + } return 0; } diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 44d4ee719..70e06ccc4 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 3d5cbd8ec..425622b79 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 347b0fc28..b4c2dd28c 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); } @@ -81,6 +83,7 @@ static struct pim_instance *pim_instance_init(struct vrf *vrf) pim_if_init(pim); + pim->mcast_if_count = 0; pim->keep_alive_time = PIM_KEEPALIVE_PERIOD; pim->rp_keep_alive_time = PIM_RP_KEEPALIVE_PERIOD; diff --git a/pimd/pim_instance.h b/pimd/pim_instance.h index 7b1fd2e17..71bd7c108 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 */ @@ -165,6 +168,7 @@ struct pim_instance { struct route_table *rp_table; int iface_vif_index[MAXVIFS]; + int mcast_if_count; struct rb_pim_oil_head channel_oil_head; diff --git a/pimd/pim_join.c b/pimd/pim_join.c index 62bd2360c..3a88de207 100644 --- a/pimd/pim_join.c +++ b/pimd/pim_join.c @@ -140,18 +140,19 @@ static void recv_prune(struct interface *ifp, struct pim_neighbor *neigh, if ((source_flags & PIM_RPT_BIT_MASK) && (source_flags & PIM_WILDCARD_BIT_MASK)) { - struct pim_rpf *rp = RP(pim_ifp->pim, sg->grp); + /* + * RFC 4601 Section 4.5.2: + * Received Prune(*,G) messages are processed even if the + * RP in the message does not match RP(G). + */ + if (PIM_DEBUG_PIM_TRACE) { + char received_rp[INET_ADDRSTRLEN]; - if (!rp) { - if (PIM_DEBUG_PIM_TRACE) - zlog_debug( - "%s: RP for %pSG4 completely failed lookup", - __func__, sg); - return; + pim_inet4_dump("<received?>", sg->src, received_rp, + sizeof(received_rp)); + zlog_debug("%s: Prune received with RP(%s) for %pSG4", + __func__, received_rp, sg); } - // Ignoring Prune *,G's at the moment. - if (sg->src.s_addr != rp->rpf_addr.u.prefix4.s_addr) - return; sg->src.s_addr = INADDR_ANY; } diff --git a/pimd/pim_memory.c b/pimd/pim_memory.c index 2bbab67e4..6bc8062c4 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 e5ca57a15..6beeb6007 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 f366fdbe7..f75bd2c1b 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -232,6 +232,8 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp, pim_upstream_mroute_iif_update(up->channel_oil, __func__); } pim_register_join(up); + /* if we have receiver, inherit from parent */ + pim_upstream_inherited_olist_decide(pim_ifp->pim, up); return 0; } @@ -961,7 +963,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(); @@ -1017,8 +1019,10 @@ static int pim_mroute_add(struct channel_oil *c_oil, const char *name) pim_channel_oil_dump(c_oil, buf, sizeof(buf))); } - c_oil->installed = 1; - c_oil->mroute_creation = pim_time_monotonic_sec(); + if (!c_oil->installed) { + c_oil->installed = 1; + c_oil->mroute_creation = pim_time_monotonic_sec(); + } return 0; } diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c index ca7ca1140..d8a797f98 100644 --- a/pimd/pim_neighbor.c +++ b/pimd/pim_neighbor.c @@ -779,6 +779,7 @@ void pim_neighbor_update(struct pim_neighbor *neigh, uint32_t dr_priority, struct list *addr_list) { struct pim_interface *pim_ifp = neigh->interface->info; + uint32_t old, new; /* Received holdtime ? */ if (PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) { @@ -818,6 +819,16 @@ void pim_neighbor_update(struct pim_neighbor *neigh, neigh->prefix_list = addr_list; update_dr_priority(neigh, hello_options, dr_priority); + new = PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_LAN_PRUNE_DELAY); + old = PIM_OPTION_IS_SET(neigh->hello_options, + PIM_OPTION_MASK_LAN_PRUNE_DELAY); + + if (old != new) { + if (old) + ++pim_ifp->pim_number_of_nonlandelay_neighbors; + else + --pim_ifp->pim_number_of_nonlandelay_neighbors; + } /* Copy flags */ diff --git a/pimd/pim_register.c b/pimd/pim_register.c index 19baecb9c..7b0af8999 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 8799134ed..a9f1d9335 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -248,13 +248,14 @@ struct rp_info *pim_rp_find_match_group(struct pim_instance *pim, if (PIM_DEBUG_PIM_TRACE) { char buf[PREFIX_STRLEN]; - route_unlock_node(rn); zlog_debug("Lookedup: %p for rp_info: %p(%s) Lock: %d", rn, rp_info, prefix2str(&rp_info->group, buf, sizeof(buf)), rn->lock); } + route_unlock_node(rn); + if (!best) return rp_info; @@ -1293,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 efa58c1b1..07f8315a1 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 8a87dfbb5..72540903b 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 569b04d27..380c97a97 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 e791500ed..8355c2099 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/ripd/rip_peer.c b/ripd/rip_peer.c index 55dafd7c1..77c73ab39 100644 --- a/ripd/rip_peer.c +++ b/ripd/rip_peer.c @@ -131,7 +131,6 @@ void rip_peer_bad_packet(struct rip *rip, struct sockaddr_in *from) static char *rip_peer_uptime(struct rip_peer *peer, char *buf, size_t len) { time_t uptime; - struct tm tm; /* If there is no connection has been done before print `never'. */ if (peer->uptime == 0) { @@ -142,17 +141,9 @@ static char *rip_peer_uptime(struct rip_peer *peer, char *buf, size_t len) /* Get current time. */ uptime = time(NULL); uptime -= peer->uptime; - gmtime_r(&uptime, &tm); - - if (uptime < ONE_DAY_SECOND) - snprintf(buf, len, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min, - tm.tm_sec); - else if (uptime < ONE_WEEK_SECOND) - snprintf(buf, len, "%dd%02dh%02dm", tm.tm_yday, tm.tm_hour, - tm.tm_min); - else - snprintf(buf, len, "%02dw%dd%02dh", tm.tm_yday / 7, - tm.tm_yday - ((tm.tm_yday / 7) * 7), tm.tm_hour); + + frrtime_to_interval(uptime, buf, len); + return buf; } diff --git a/ripngd/ripng_peer.c b/ripngd/ripng_peer.c index c038bfccf..e6ff58dd0 100644 --- a/ripngd/ripng_peer.c +++ b/ripngd/ripng_peer.c @@ -141,7 +141,6 @@ void ripng_peer_bad_packet(struct ripng *ripng, struct sockaddr_in6 *from) static char *ripng_peer_uptime(struct ripng_peer *peer, char *buf, size_t len) { time_t uptime; - struct tm tm; /* If there is no connection has been done before print `never'. */ if (peer->uptime == 0) { @@ -152,17 +151,9 @@ static char *ripng_peer_uptime(struct ripng_peer *peer, char *buf, size_t len) /* Get current time. */ uptime = time(NULL); uptime -= peer->uptime; - gmtime_r(&uptime, &tm); - - if (uptime < ONE_DAY_SECOND) - snprintf(buf, len, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min, - tm.tm_sec); - else if (uptime < ONE_WEEK_SECOND) - snprintf(buf, len, "%dd%02dh%02dm", tm.tm_yday, tm.tm_hour, - tm.tm_min); - else - snprintf(buf, len, "%02dw%dd%02dh", tm.tm_yday / 7, - tm.tm_yday - ((tm.tm_yday / 7) * 7), tm.tm_hour); + + frrtime_to_interval(uptime, buf, len); + return buf; } diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c index 486ccf6bf..fd2e37e67 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 5baa74fe9..882e73f87 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 57ffcc769..c995d557a 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/staticd/static_vty.c b/staticd/static_vty.c index 40bcf2b5d..a950b0473 100644 --- a/staticd/static_vty.c +++ b/staticd/static_vty.c @@ -867,7 +867,7 @@ DEFPY(ip_route_address_interface, "Table to configure\n" "The table number to configure\n" VRF_CMD_HELP_STR - "Treat the nexthop as directly attached to the interface") + "Treat the nexthop as directly attached to the interface\n") { struct static_vrf *svrf; struct static_vrf *nh_svrf; @@ -935,7 +935,7 @@ DEFPY(ip_route_address_interface_vrf, "Table to configure\n" "The table number to configure\n" VRF_CMD_HELP_STR - "Treat the nexthop as directly attached to the interface") + "Treat the nexthop as directly attached to the interface\n") { VTY_DECLVAR_CONTEXT(vrf, vrf); const char *flag = NULL; @@ -1211,7 +1211,7 @@ DEFPY(ipv6_route_address_interface, "Table to configure\n" "The table number to configure\n" VRF_CMD_HELP_STR - "Treat the nexthop as directly attached to the interface") + "Treat the nexthop as directly attached to the interface\n") { struct static_vrf *svrf; struct static_vrf *nh_svrf; @@ -1279,7 +1279,7 @@ DEFPY(ipv6_route_address_interface_vrf, "Table to configure\n" "The table number to configure\n" VRF_CMD_HELP_STR - "Treat the nexthop as directly attached to the interface") + "Treat the nexthop as directly attached to the interface\n") { VTY_DECLVAR_CONTEXT(vrf, vrf); struct static_vrf *svrf = vrf->info; diff --git a/tests/bgpd/test_aspath.c b/tests/bgpd/test_aspath.c index 9feec7156..b94355e8b 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 15ae514c8..5fa1f1162 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 c97ea5715..7fabaad7f 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/isisd/test_fuzz_isis_tlv_tests.h.gz b/tests/isisd/test_fuzz_isis_tlv_tests.h.gz Binary files differindex 46e45e5ee..4f59d1d7c 100644 --- a/tests/isisd/test_fuzz_isis_tlv_tests.h.gz +++ b/tests/isisd/test_fuzz_isis_tlv_tests.h.gz 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 16609221c..a671e14e0 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 59858d6fd..e2bd80daa 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-basic-functionality-topo1/test_bgp_basic_functionality.py b/tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py index e99111d90..43639a81d 100755 --- a/tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py +++ b/tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py @@ -79,6 +79,9 @@ try: except IOError: assert False, "Could not read file {}".format(jsonFile) +#Global Variable +KEEPALIVETIMER = 2 +HOLDDOWNTIMER = 6 class CreateTopo(Topo): """ @@ -292,8 +295,8 @@ def test_bgp_timers_functionality(request): "r2": { "dest_link":{ "r1": { - "keepalivetimer": 60, - "holddowntimer": 180, + "keepalivetimer": KEEPALIVETIMER, + "holddowntimer": HOLDDOWNTIMER } } } @@ -319,8 +322,6 @@ def test_bgp_timers_functionality(request): write_test_footer(tc_name) - - def test_static_routes(request): """ Test to create and verify static routes. """ diff --git a/tests/topotests/bgp_prefix_sid/__init__.py b/tests/topotests/bgp_prefix_sid/__init__.py new file mode 100644 index 000000000..e69de29bb --- /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 000000000..6c554f5fa --- /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 000000000..5b55366a0 --- /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 000000000..eaa6a6787 --- /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 000000000..dabd88e03 --- /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 000000000..7a38cc307 --- /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 000000000..0cd26052f --- /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 000000000..dc203cabc --- /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/ldp-oc-acl-topo1/r1/ldpd.conf b/tests/topotests/ldp-oc-acl-topo1/r1/ldpd.conf new file mode 100644 index 000000000..85bb970fd --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r1/ldpd.conf @@ -0,0 +1,25 @@ +hostname r1 +log file ldpd.log +! +debug mpls ldp zebra +debug mpls ldp event +debug mpls ldp errors +debug mpls ldp messages recv +debug mpls ldp messages sent +debug mpls ldp discovery hello recv +debug mpls ldp discovery hello sent +! +mpls ldp + router-id 1.1.1.1 + ordered-control + ! + address-family ipv4 + discovery transport-address 1.1.1.1 + label local allocate host-routes + ! + interface r1-eth0 + ! + ! +! +line vty +! diff --git a/tests/topotests/ldp-oc-acl-topo1/r1/ospfd.conf b/tests/topotests/ldp-oc-acl-topo1/r1/ospfd.conf new file mode 100644 index 000000000..6daf034d1 --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r1/ospfd.conf @@ -0,0 +1,7 @@ +hostname r1 +log file ospfd.log +! +router ospf + router-id 1.1.1.1 + network 0.0.0.0/0 area 0 +! diff --git a/tests/topotests/ldp-oc-acl-topo1/r1/show_ip_ospf_neighbor.json b/tests/topotests/ldp-oc-acl-topo1/r1/show_ip_ospf_neighbor.json new file mode 100644 index 000000000..2c493173f --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r1/show_ip_ospf_neighbor.json @@ -0,0 +1,12 @@ +{ + "neighbors":{ + "2.2.2.2":[ + { + "priority":1, + "state":"Full\/DR", + "address":"10.0.1.2", + "ifaceName":"r1-eth0:10.0.1.1" + } + ] + } +} diff --git a/tests/topotests/ldp-oc-acl-topo1/r1/show_ip_route.ref b/tests/topotests/ldp-oc-acl-topo1/r1/show_ip_route.ref new file mode 100644 index 000000000..d75b8f21d --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r1/show_ip_route.ref @@ -0,0 +1,171 @@ +{ + "1.1.1.1/32":[ + { + "prefix":"1.1.1.1/32", + "protocol":"ospf", + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":1, + "interfaceName":"lo", + "active":true + } + ] + }, + { + "prefix":"1.1.1.1/32", + "protocol":"connected", + "selected":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":1, + "interfaceName":"lo", + "active":true + } + ] + } + ], + "2.2.2.2/32":[ + { + "prefix":"2.2.2.2/32", + "protocol":"ospf", + "selected":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.1.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r1-eth0", + "active":true + } + ] + } + ], + "3.3.3.3/32":[ + { + "prefix":"3.3.3.3/32", + "protocol":"ospf", + "selected":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.1.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r1-eth0", + "active":true + } + ] + } + ], + "4.4.4.4/32":[ + { + "prefix":"4.4.4.4/32", + "protocol":"ospf", + "selected":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.1.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r1-eth0", + "active":true + } + ] + } + ], + "10.0.1.0/24":[ + { + "prefix":"10.0.1.0/24", + "protocol":"ospf", + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r1-eth0", + "active":true + } + ] + }, + { + "prefix":"10.0.1.0/24", + "protocol":"connected", + "selected":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r1-eth0", + "active":true + } + ] + } + ], + "10.0.2.0/24":[ + { + "prefix":"10.0.2.0/24", + "protocol":"ospf", + "selected":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.1.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r1-eth0", + "active":true + } + ] + } + ], + "10.0.3.0/24":[ + { + "prefix":"10.0.3.0/24", + "protocol":"ospf", + "selected":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.1.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r1-eth0", + "active":true + } + ] + } + ], + "123.0.1.0/24":[ + { + "prefix":"123.0.1.0/24", + "protocol":"ospf", + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r1-eth0", + "active":true + } + ] + }, + { + "prefix":"123.0.1.0/24", + "protocol":"connected", + "selected":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r1-eth0", + "active":true + } + ] + } + ] +} diff --git a/tests/topotests/ldp-oc-acl-topo1/r1/show_ldp_binding.ref b/tests/topotests/ldp-oc-acl-topo1/r1/show_ldp_binding.ref new file mode 100644 index 000000000..ccc841364 --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r1/show_ldp_binding.ref @@ -0,0 +1,55 @@ +{ + "bindings":[ + { + "addressFamily":"ipv4", + "prefix":"1.1.1.1/32", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"2.2.2.2/32", + "neighborId":"2.2.2.2", + "remoteLabel":"imp-null", + "inUse":1 + }, + { + "addressFamily":"ipv4", + "prefix":"3.3.3.3/32", + "neighborId":"2.2.2.2", + "inUse":1 + }, + { + "addressFamily":"ipv4", + "prefix":"4.4.4.4/32", + "neighborId":"0.0.0.0", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.1.0/24", + "neighborId":"2.2.2.2", + "localLabel":"-", + "remoteLabel":"imp-null", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.2.0/24", + "neighborId":"2.2.2.2", + "localLabel":"-", + "remoteLabel":"imp-null", + "inUse":1 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.3.0/24", + "neighborId":"2.2.2.2", + "localLabel":"-", + "inUse":1 + } + ] +} diff --git a/tests/topotests/ldp-oc-acl-topo1/r1/show_ldp_discovery.ref b/tests/topotests/ldp-oc-acl-topo1/r1/show_ldp_discovery.ref new file mode 100644 index 000000000..b349f4418 --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r1/show_ldp_discovery.ref @@ -0,0 +1,11 @@ +{ + "adjacencies":[ + { + "addressFamily":"ipv4", + "neighborId":"2.2.2.2", + "type":"link", + "interface":"r1-eth0", + "helloHoldtime":15 + } + ] +} diff --git a/tests/topotests/ldp-oc-acl-topo1/r1/show_ldp_neighbor.ref b/tests/topotests/ldp-oc-acl-topo1/r1/show_ldp_neighbor.ref new file mode 100644 index 000000000..4bff444a4 --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r1/show_ldp_neighbor.ref @@ -0,0 +1,10 @@ +{ + "neighbors":[ + { + "addressFamily":"ipv4", + "neighborId":"2.2.2.2", + "state":"OPERATIONAL", + "transportAddress":"2.2.2.2" + } + ] +} diff --git a/tests/topotests/ldp-oc-acl-topo1/r1/zebra.conf b/tests/topotests/ldp-oc-acl-topo1/r1/zebra.conf new file mode 100644 index 000000000..83aea46e6 --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r1/zebra.conf @@ -0,0 +1,17 @@ +log file zebra.log +! +hostname r1 +! +interface lo + ip address 1.1.1.1/32 +! +interface r1-eth0 + description to sw0 + ip address 10.0.1.1/24 + ip address 123.0.1.1/24 +! +ip forwarding +! +! +line vty +! diff --git a/tests/topotests/ldp-oc-acl-topo1/r2/ldpd.conf b/tests/topotests/ldp-oc-acl-topo1/r2/ldpd.conf new file mode 100644 index 000000000..e1a552c70 --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r2/ldpd.conf @@ -0,0 +1,28 @@ +hostname r2 +log file ldpd.log +! +debug mpls ldp zebra +debug mpls ldp event +debug mpls ldp errors +debug mpls ldp messages recv +debug mpls ldp messages sent +debug mpls ldp discovery hello recv +debug mpls ldp discovery hello sent +! +mpls ldp + router-id 2.2.2.2 + ordered-control + ! + address-family ipv4 + discovery transport-address 2.2.2.2 + ! + interface r2-eth0 + ! + interface r2-eth1 + ! + interface r2-eth2 + ! + ! +! +line vty +! diff --git a/tests/topotests/ldp-oc-acl-topo1/r2/ospfd.conf b/tests/topotests/ldp-oc-acl-topo1/r2/ospfd.conf new file mode 100644 index 000000000..867881366 --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r2/ospfd.conf @@ -0,0 +1,7 @@ +hostname r2 +log file ospfd.log +! +router ospf + router-id 2.2.2.2 + network 0.0.0.0/0 area 0 +! diff --git a/tests/topotests/ldp-oc-acl-topo1/r2/show_ip_ospf_neighbor.json b/tests/topotests/ldp-oc-acl-topo1/r2/show_ip_ospf_neighbor.json new file mode 100644 index 000000000..55f12359e --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r2/show_ip_ospf_neighbor.json @@ -0,0 +1,31 @@ +{ + "neighbors":{ + "1.1.1.1":[ + { + "priority":1, + "state":"Full\/Backup", + "address":"10.0.1.1", + "ifaceName":"r2-eth0:10.0.1.2", + "retransmitCounter":0, + "requestCounter":0, + "dbSummaryCounter":0 + } + ], + "3.3.3.3":[ + { + "priority":1, + "state":"Full\/Backup", + "address":"10.0.2.3", + "ifaceName":"r2-eth1:10.0.2.2" + } + ], + "4.4.4.4":[ + { + "priority":1, + "state":"Full\/DR", + "address":"10.0.2.4", + "ifaceName":"r2-eth1:10.0.2.2" + } + ] + } +} diff --git a/tests/topotests/ldp-oc-acl-topo1/r2/show_ip_route.ref b/tests/topotests/ldp-oc-acl-topo1/r2/show_ip_route.ref new file mode 100644 index 000000000..060c0b429 --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r2/show_ip_route.ref @@ -0,0 +1,209 @@ +{ + "1.1.1.1/32":[ + { + "prefix":"1.1.1.1/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":10, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.1.1", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r2-eth0", + "active":true + } + ] + } + ], + "2.2.2.2/32":[ + { + "prefix":"2.2.2.2/32", + "protocol":"ospf", + "distance":110, + "metric":0, + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":1, + "interfaceName":"lo", + "active":true + } + ] + }, + { + "prefix":"2.2.2.2/32", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":1, + "interfaceName":"lo", + "active":true + } + ] + } + ], + "3.3.3.3/32":[ + { + "prefix":"3.3.3.3/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":10, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.3", + "afi":"ipv4", + "interfaceIndex":3, + "interfaceName":"r2-eth1", + "active":true + } + ] + } + ], + "4.4.4.4/32":[ + { + "prefix":"4.4.4.4/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":10, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.4", + "afi":"ipv4", + "interfaceIndex":3, + "interfaceName":"r2-eth1", + "active":true + } + ] + } + ], + "10.0.1.0\/24":[ + { + "prefix":"10.0.1.0\/24", + "protocol":"ospf", + "distance":110, + "metric":10, + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r2-eth0", + "active":true + } + ] + }, + { + "prefix":"10.0.1.0\/24", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r2-eth0", + "active":true + } + ] + } + ], + "10.0.2.0\/24":[ + { + "prefix":"10.0.2.0\/24", + "protocol":"ospf", + "distance":110, + "metric":10, + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":3, + "interfaceName":"r2-eth1", + "active":true + } + ] + }, + { + "prefix":"10.0.2.0\/24", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":3, + "interfaceName":"r2-eth1", + "active":true + } + ] + } + ], + "10.0.3.0\/24":[ + { + "prefix":"10.0.3.0\/24", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":20, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.3", + "afi":"ipv4", + "interfaceIndex":3, + "interfaceName":"r2-eth1", + "active":true + } + ] + } + ], + "123.0.1.0\/24":[ + { + "prefix":"123.0.1.0\/24", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":20, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.1.1", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r2-eth0", + "active":true + } + ] + } + ] +} diff --git a/tests/topotests/ldp-oc-acl-topo1/r2/show_ldp_binding.ref b/tests/topotests/ldp-oc-acl-topo1/r2/show_ldp_binding.ref new file mode 100644 index 000000000..ea32de3ed --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r2/show_ldp_binding.ref @@ -0,0 +1,63 @@ +{ + "bindings":[ + { + "addressFamily":"ipv4", + "prefix":"1.1.1.1/32", + "neighborId":"1.1.1.1", + "remoteLabel":"imp-null", + "inUse":1 + }, + { + "addressFamily":"ipv4", + "prefix":"2.2.2.2/32", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"3.3.3.3/32", + "neighborId":"3.3.3.3", + "remoteLabel":"imp-null", + "inUse":1 + }, + { + "addressFamily":"ipv4", + "prefix":"4.4.4.4/32", + "neighborId":"0.0.0.0", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.1.0/24", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.2.0/24", + "neighborId":"3.3.3.3", + "localLabel":"imp-null", + "remoteLabel":"imp-null", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.3.0/24", + "neighborId":"3.3.3.3", + "remoteLabel":"imp-null", + "inUse":1 + }, + { + "addressFamily":"ipv4", + "prefix":"123.0.1.0/24", + "neighborId":"0.0.0.0", + "remoteLabel":"-", + "inUse":0 + } + ] +} diff --git a/tests/topotests/ldp-oc-acl-topo1/r2/show_ldp_discovery.ref b/tests/topotests/ldp-oc-acl-topo1/r2/show_ldp_discovery.ref new file mode 100644 index 000000000..812957008 --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r2/show_ldp_discovery.ref @@ -0,0 +1,18 @@ +{ + "adjacencies":[ + { + "addressFamily":"ipv4", + "neighborId":"1.1.1.1", + "type":"link", + "interface":"r2-eth0", + "helloHoldtime":15 + }, + { + "addressFamily":"ipv4", + "neighborId":"3.3.3.3", + "type":"link", + "interface":"r2-eth1", + "helloHoldtime":15 + } + ] +} diff --git a/tests/topotests/ldp-oc-acl-topo1/r2/show_ldp_neighbor.ref b/tests/topotests/ldp-oc-acl-topo1/r2/show_ldp_neighbor.ref new file mode 100644 index 000000000..eed35289e --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r2/show_ldp_neighbor.ref @@ -0,0 +1,16 @@ +{ + "neighbors":[ + { + "addressFamily":"ipv4", + "neighborId":"1.1.1.1", + "state":"OPERATIONAL", + "transportAddress":"1.1.1.1" + }, + { + "addressFamily":"ipv4", + "neighborId":"3.3.3.3", + "state":"OPERATIONAL", + "transportAddress":"3.3.3.3" + } + ] +} diff --git a/tests/topotests/ldp-oc-acl-topo1/r2/zebra.conf b/tests/topotests/ldp-oc-acl-topo1/r2/zebra.conf new file mode 100644 index 000000000..1f1e3e391 --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r2/zebra.conf @@ -0,0 +1,27 @@ +log file zebra.log +! +hostname r2 +! +interface lo + ip address 2.2.2.2/32 +! +interface r2-eth0 + description to sw0 + ip address 10.0.1.2/24 +! no link-detect +! +interface r2-eth1 + description to sw1 + ip address 10.0.2.2/24 +! no link-detect +! +interface r2-eths2 + description to sw2 + ip address 10.0.3.2/24 +! no link-detect +! +ip forwarding +! +! +line vty +! diff --git a/tests/topotests/ldp-oc-acl-topo1/r3/ldpd.conf b/tests/topotests/ldp-oc-acl-topo1/r3/ldpd.conf new file mode 100644 index 000000000..4e66b140a --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r3/ldpd.conf @@ -0,0 +1,24 @@ +hostname r3 +log file ldpd.log +! +debug mpls ldp zebra +debug mpls ldp event +debug mpls ldp errors +debug mpls ldp messages recv +debug mpls ldp messages sent +debug mpls ldp discovery hello recv +debug mpls ldp discovery hello sent +! +mpls ldp + router-id 3.3.3.3 + ordered-control + ! + address-family ipv4 + discovery transport-address 3.3.3.3 + ! + interface r3-eth0 + ! + ! +! +line vty +! diff --git a/tests/topotests/ldp-oc-acl-topo1/r3/ospfd.conf b/tests/topotests/ldp-oc-acl-topo1/r3/ospfd.conf new file mode 100644 index 000000000..202be238e --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r3/ospfd.conf @@ -0,0 +1,8 @@ +hostname r3 +password 1 +log file ospfd.log +! +router ospf + router-id 3.3.3.3 + network 0.0.0.0/0 area 0 +! diff --git a/tests/topotests/ldp-oc-acl-topo1/r3/show_ip_ospf_neighbor.json b/tests/topotests/ldp-oc-acl-topo1/r3/show_ip_ospf_neighbor.json new file mode 100644 index 000000000..24502ed81 --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r3/show_ip_ospf_neighbor.json @@ -0,0 +1,20 @@ +{ + "neighbors":{ + "2.2.2.2":[ + { + "priority":1, + "state":"Full\/DROther", + "address":"10.0.2.2", + "ifaceName":"r3-eth0:10.0.2.3" + } + ], + "4.4.4.4":[ + { + "priority":1, + "state":"Full\/DR", + "address":"10.0.2.4", + "ifaceName":"r3-eth0:10.0.2.3" + } + ] + } +} diff --git a/tests/topotests/ldp-oc-acl-topo1/r3/show_ip_route.ref b/tests/topotests/ldp-oc-acl-topo1/r3/show_ip_route.ref new file mode 100644 index 000000000..40800762b --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r3/show_ip_route.ref @@ -0,0 +1,209 @@ +{ + "1.1.1.1/32":[ + { + "prefix":"1.1.1.1/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":20, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r3-eth0", + "active":true + } + ] + } + ], + "2.2.2.2/32":[ + { + "prefix":"2.2.2.2/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":10, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r3-eth0", + "active":true + } + ] + } + ], + "3.3.3.3/32":[ + { + "prefix":"3.3.3.3/32", + "protocol":"ospf", + "distance":110, + "metric":0, + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":1, + "interfaceName":"lo", + "active":true + } + ] + }, + { + "prefix":"3.3.3.3/32", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":1, + "interfaceName":"lo", + "active":true + } + ] + } + ], + "4.4.4.4/32":[ + { + "prefix":"4.4.4.4/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":10, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.4", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r3-eth0", + "active":true + } + ] + } + ], + "10.0.1.0\/24":[ + { + "prefix":"10.0.1.0\/24", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":20, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r3-eth0", + "active":true + } + ] + } + ], + "10.0.2.0\/24":[ + { + "prefix":"10.0.2.0\/24", + "protocol":"ospf", + "distance":110, + "metric":10, + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r3-eth0", + "active":true + } + ] + }, + { + "prefix":"10.0.2.0\/24", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r3-eth0", + "active":true + } + ] + } + ], + "10.0.3.0\/24":[ + { + "prefix":"10.0.3.0\/24", + "protocol":"ospf", + "distance":110, + "metric":10, + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":3, + "interfaceName":"r3-eth1", + "active":true + } + ] + }, + { + "prefix":"10.0.3.0\/24", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":3, + "interfaceName":"r3-eth1", + "active":true + } + ] + } + ], + "123.0.1.0\/24":[ + { + "prefix":"123.0.1.0\/24", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":30, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r3-eth0", + "active":true + } + ] + } + ] +} diff --git a/tests/topotests/ldp-oc-acl-topo1/r3/show_ldp_binding.ref b/tests/topotests/ldp-oc-acl-topo1/r3/show_ldp_binding.ref new file mode 100644 index 000000000..bb1b2b302 --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r3/show_ldp_binding.ref @@ -0,0 +1,62 @@ +{ + "bindings":[ + { + "addressFamily":"ipv4", + "prefix":"1.1.1.1/32", + "neighborId":"2.2.2.2", + "inUse":1 + }, + { + "addressFamily":"ipv4", + "prefix":"2.2.2.2/32", + "neighborId":"2.2.2.2", + "remoteLabel":"imp-null", + "inUse":1 + }, + { + "addressFamily":"ipv4", + "prefix":"3.3.3.3/32", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"4.4.4.4/32", + "neighborId":"0.0.0.0", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.1.0/24", + "neighborId":"2.2.2.2", + "remoteLabel":"imp-null", + "inUse":1 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.2.0/24", + "neighborId":"2.2.2.2", + "localLabel":"imp-null", + "remoteLabel":"imp-null", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.3.0/24", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"123.0.1.0/24", + "neighborId":"0.0.0.0", + "remoteLabel":"-", + "inUse":0 + } + ] +} diff --git a/tests/topotests/ldp-oc-acl-topo1/r3/show_ldp_discovery.ref b/tests/topotests/ldp-oc-acl-topo1/r3/show_ldp_discovery.ref new file mode 100644 index 000000000..c3a07e7e3 --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r3/show_ldp_discovery.ref @@ -0,0 +1,11 @@ +{ + "adjacencies":[ + { + "addressFamily":"ipv4", + "neighborId":"2.2.2.2", + "type":"link", + "interface":"r3-eth0", + "helloHoldtime":15 + } + ] +} diff --git a/tests/topotests/ldp-oc-acl-topo1/r3/show_ldp_neighbor.ref b/tests/topotests/ldp-oc-acl-topo1/r3/show_ldp_neighbor.ref new file mode 100644 index 000000000..4bff444a4 --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r3/show_ldp_neighbor.ref @@ -0,0 +1,10 @@ +{ + "neighbors":[ + { + "addressFamily":"ipv4", + "neighborId":"2.2.2.2", + "state":"OPERATIONAL", + "transportAddress":"2.2.2.2" + } + ] +} diff --git a/tests/topotests/ldp-oc-acl-topo1/r3/zebra.conf b/tests/topotests/ldp-oc-acl-topo1/r3/zebra.conf new file mode 100644 index 000000000..234c215dd --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r3/zebra.conf @@ -0,0 +1,22 @@ +log file zebra.log +! +hostname r3 +! +interface lo + ip address 3.3.3.3/32 +! +interface r3-eth0 + description to sw1 + ip address 10.0.2.3/24 +! no link-detect +! +interface r3-eth1 + description to sw2 + ip address 10.0.3.3/24 +! no link-detect +! +ip forwarding +! +! +line vty +! diff --git a/tests/topotests/ldp-oc-acl-topo1/r4/ldpd.conf b/tests/topotests/ldp-oc-acl-topo1/r4/ldpd.conf new file mode 100644 index 000000000..6b7d28f98 --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r4/ldpd.conf @@ -0,0 +1,24 @@ +hostname r4 +log file ldpd.log +! +debug mpls ldp zebra +debug mpls ldp event +debug mpls ldp errors +debug mpls ldp messages recv +debug mpls ldp messages sent +debug mpls ldp discovery hello recv +debug mpls ldp discovery hello sent +! +mpls ldp + router-id 4.4.4.4 + ordered-control + ! + address-family ipv4 + discovery transport-address 4.4.4.4 + ! + !interface r4-eth0 + ! + ! +! +line vty +! diff --git a/tests/topotests/ldp-oc-acl-topo1/r4/ospfd.conf b/tests/topotests/ldp-oc-acl-topo1/r4/ospfd.conf new file mode 100644 index 000000000..569dbc54e --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r4/ospfd.conf @@ -0,0 +1,7 @@ +hostname r4 +log file ospfd.log +! +router ospf + router-id 4.4.4.4 + network 0.0.0.0/0 area 0 +! diff --git a/tests/topotests/ldp-oc-acl-topo1/r4/show_ip_ospf_neighbor.json b/tests/topotests/ldp-oc-acl-topo1/r4/show_ip_ospf_neighbor.json new file mode 100644 index 000000000..794410522 --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r4/show_ip_ospf_neighbor.json @@ -0,0 +1,21 @@ + +{ + "neighbors":{ + "2.2.2.2":[ + { + "priority":1, + "state":"Full\/DROther", + "address":"10.0.2.2", + "ifaceName":"r4-eth0:10.0.2.4" + } + ], + "3.3.3.3":[ + { + "priority":1, + "state":"Full\/Backup", + "address":"10.0.2.3", + "ifaceName":"r4-eth0:10.0.2.4" + } + ] + } +} diff --git a/tests/topotests/ldp-oc-acl-topo1/r4/show_ip_route.ref b/tests/topotests/ldp-oc-acl-topo1/r4/show_ip_route.ref new file mode 100644 index 000000000..c9b83a1c7 --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r4/show_ip_route.ref @@ -0,0 +1,196 @@ +{ + "1.1.1.1/32":[ + { + "prefix":"1.1.1.1/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":20, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r4-eth0", + "active":true + } + ] + } + ], + "2.2.2.2/32":[ + { + "prefix":"2.2.2.2/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":10, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r4-eth0", + "active":true + } + ] + } + ], + "3.3.3.3/32":[ + { + "prefix":"3.3.3.3/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":10, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.3", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r4-eth0", + "active":true + } + ] + } + ], + "4.4.4.4/32":[ + { + "prefix":"4.4.4.4/32", + "protocol":"ospf", + "distance":110, + "metric":0, + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":1, + "interfaceName":"lo", + "active":true + } + ] + }, + { + "prefix":"4.4.4.4/32", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":1, + "interfaceName":"lo", + "active":true + } + ] + } + ], + "10.0.1.0\/24":[ + { + "prefix":"10.0.1.0\/24", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":20, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r4-eth0", + "active":true + } + ] + } + ], + "10.0.2.0\/24":[ + { + "prefix":"10.0.2.0\/24", + "protocol":"ospf", + "distance":110, + "metric":10, + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r4-eth0", + "active":true + } + ] + }, + { + "prefix":"10.0.2.0\/24", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r4-eth0", + "active":true + } + ] + } + ], + "10.0.3.0\/24":[ + { + "prefix":"10.0.3.0\/24", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":20, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.3", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r4-eth0", + "active":true + } + ] + } + ], + "123.0.1.0\/24":[ + { + "prefix":"123.0.1.0\/24", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":30, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r4-eth0", + "active":true + } + ] + } + ] +} diff --git a/tests/topotests/ldp-oc-acl-topo1/r4/show_ldp_binding.ref b/tests/topotests/ldp-oc-acl-topo1/r4/show_ldp_binding.ref new file mode 100644 index 000000000..2a46c4034 --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r4/show_ldp_binding.ref @@ -0,0 +1,68 @@ +{ + "bindings":[ + { + "addressFamily":"ipv4", + "prefix":"1.1.1.1/32", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"2.2.2.2/32", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"3.3.3.3/32", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"4.4.4.4/32", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.1.0/24", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.2.0/24", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.3.0/24", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"123.0.1.0/24", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + } + ] +} diff --git a/tests/topotests/ldp-oc-acl-topo1/r4/show_ldp_discovery.ref b/tests/topotests/ldp-oc-acl-topo1/r4/show_ldp_discovery.ref new file mode 100644 index 000000000..2c63c0851 --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r4/show_ldp_discovery.ref @@ -0,0 +1,2 @@ +{ +} diff --git a/tests/topotests/ldp-oc-acl-topo1/r4/show_ldp_neighbor.ref b/tests/topotests/ldp-oc-acl-topo1/r4/show_ldp_neighbor.ref new file mode 100644 index 000000000..2c63c0851 --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r4/show_ldp_neighbor.ref @@ -0,0 +1,2 @@ +{ +} diff --git a/tests/topotests/ldp-oc-acl-topo1/r4/zebra.conf b/tests/topotests/ldp-oc-acl-topo1/r4/zebra.conf new file mode 100644 index 000000000..7e291053e --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/r4/zebra.conf @@ -0,0 +1,17 @@ +log file zebra.log +! +hostname r4 +! +interface lo + ip address 4.4.4.4/32 +! +interface r4-eth0 + description to sw1 + ip address 10.0.2.4/24 +! no link-detect +! +ip forwarding +! +! +line vty +! diff --git a/tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.dot b/tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.dot new file mode 100644 index 000000000..62058e3cb --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.dot @@ -0,0 +1,76 @@ +## Color coding: +######################### +## Main FRR: #f08080 red +## Switches: #d0e0d0 gray +## RIP: #19e3d9 Cyan +## RIPng: #fcb314 dark yellow +## OSPFv2: #32b835 Green +## OSPFv3: #19e3d9 Cyan +## ISIS IPv4 #fcb314 dark yellow +## ISIS IPv6 #9a81ec purple +## BGP IPv4 #eee3d3 beige +## BGP IPv6 #fdff00 yellow +##### Colors (see http://www.color-hex.com/) + +graph template { + label="Test Topology - LDP-OC 1"; + + # Routers + r1 [ + shape=doubleoctagon, + label="r1", + fillcolor="#f08080", + style=filled, + ]; + r2 [ + shape=doubleoctagon + label="r2", + fillcolor="#f08080", + style=filled, + ]; + r3 [ + shape=doubleoctagon + label="r3", + fillcolor="#f08080", + style=filled, + ]; + r4 [ + shape=doubleoctagon + label="r4", + fillcolor="#f08080", + style=filled, + ]; + + + # Switches + s0 [ + shape=oval, + label="10.0.1.0/24", + fillcolor="#d0e0d0", + style=filled, + ]; + s1 [ + shape=oval, + label="10.0.2.0/24", + fillcolor="#d0e0d0", + style=filled, + ]; + s2 [ + shape=oval, + label="10.0.3.0/24", + fillcolor="#d0e0d0", + style=filled, + ]; + + # Connections + + r1 -- s0 [label="eth0"]; + r2 -- s0 [label="eth0"]; + + r2 -- s1 [label="eth1"]; + r3 -- s1 [label="eth0"]; + r4 -- s1 [label="eth0"]; + + r2 -- s2 [label="eth2"]; + r3 -- s2 [label="eth1"]; +} diff --git a/tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.py b/tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.py new file mode 100755 index 000000000..47b32a16e --- /dev/null +++ b/tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.py @@ -0,0 +1,227 @@ +#!/usr/bin/env python + +# +# test_ldp_oc_acl_topo1.py +# Part of NetDEF Topology Tests +# +# Copyright (c) 2020 by Volta Networks +# +# 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_ldp_oc_acl_topo1.py: Simple FRR/Quagga LDP Test + + +---------+ + | r1 | + | 1.1.1.1 | + +----+----+ + | .1 r1-eth0 + | + ~~~~~~~~~~~~~ + ~~ sw0 ~~ + ~~ 10.0.1.0/24 ~~ + ~~~~~~~~~~~~~ + |10.0.1.0/24 + | + | .2 r2-eth0 + +----+----+ + | r2 | + | 2.2.2.2 | + +--+---+--+ + r2-eth2 .2 | | .2 r2-eth1 + ______/ \______ + / \ + ~~~~~~~~~~~~~ ~~~~~~~~~~~~~ +~~ sw2 ~~ ~~ sw1 ~~ +~~ 10.0.3.0/24 ~~ ~~ 10.0.2.0/24 ~~ + ~~~~~~~~~~~~~ ~~~~~~~~~~~~~ + | / | + \ _________/ | + \ / \ +r3-eth1 .3 | | .3 r3-eth0 | .4 r4-eth0 + +----+--+---+ +----+----+ + | r3 | | r4 | + | 3.3.3.3 | | 4.4.4.4 | + +-----------+ +---------+ +""" + +import os +import sys +import pytest +import json +from time import sleep +from functools import partial + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, '../')) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger + +# Required to instantiate the topology builder class. +from mininet.topo import Topo + +class TemplateTopo(Topo): + "Test topology builder" + def build(self, *_args, **_opts): + "Build function" + tgen = get_topogen(self) + + # + # Define FRR Routers + # + for router in ['r1', 'r2', 'r3', 'r4']: + tgen.add_router(router) + + # + # Define connections + # + switch = tgen.add_switch('s0') + switch.add_link(tgen.gears['r1']) + switch.add_link(tgen.gears['r2']) + + switch = tgen.add_switch('s1') + switch.add_link(tgen.gears['r2']) + switch.add_link(tgen.gears['r3']) + switch.add_link(tgen.gears['r4']) + + switch = tgen.add_switch('s2') + switch.add_link(tgen.gears['r2']) + switch.add_link(tgen.gears['r3']) + +def setup_module(mod): + "Sets up the pytest environment" + tgen = Topogen(TemplateTopo, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + # For all registered routers, load the zebra configuration file + for rname, router in router_list.iteritems(): + router.load_config( + TopoRouter.RD_ZEBRA, + os.path.join(CWD, '{}/zebra.conf'.format(rname)) + ) + # Don't start ospfd and ldpd in the CE nodes + if router.name[0] == 'r': + router.load_config( + TopoRouter.RD_OSPF, + os.path.join(CWD, '{}/ospfd.conf'.format(rname)) + ) + router.load_config( + TopoRouter.RD_LDP, + os.path.join(CWD, '{}/ldpd.conf'.format(rname)) + ) + + tgen.start_router() + +def teardown_module(mod): + "Teardown the pytest environment" + tgen = get_topogen() + + # This function tears down the whole topology. + tgen.stop_topology() + + +def router_compare_json_output(rname, command, reference): + "Compare router JSON output" + + logger.info('Comparing router "%s" "%s" output', rname, command) + + tgen = get_topogen() + filename = '{}/{}/{}'.format(CWD, rname, reference) + expected = json.loads(open(filename).read()) + + # Run test function until we get an result. Wait at most 80 seconds. + test_func = partial(topotest.router_json_cmp, + tgen.gears[rname], command, expected) + _, diff = topotest.run_and_expect(test_func, None, count=160, wait=0.5) + + assertmsg = '"{}" JSON output mismatches the expected result'.format(rname) + assert diff is None, assertmsg + +def test_ospf_convergence(): + logger.info("Test: check OSPF adjacencies") + + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + for rname in ['r1', 'r2', 'r3', 'r4']: + router_compare_json_output(rname, "show ip ospf neighbor json", "show_ip_ospf_neighbor.json") + +def test_rib(): + logger.info("Test: verify RIB") + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + for rname in ['r1', 'r2', 'r3', 'r4']: + router_compare_json_output(rname, "show ip route json", "show_ip_route.ref") + +def test_ldp_adjacencies(): + logger.info("Test: verify LDP adjacencies") + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + for rname in ['r1', 'r2', 'r3', 'r4']: + router_compare_json_output(rname, "show mpls ldp discovery json", "show_ldp_discovery.ref") + +def test_ldp_neighbors(): + logger.info("Test: verify LDP neighbors") + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + for rname in ['r1', 'r2', 'r3', 'r4']: + router_compare_json_output(rname, "show mpls ldp neighbor json", "show_ldp_neighbor.ref") + +def test_ldp_bindings(): + logger.info("Test: verify LDP bindings") + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + for rname in ['r1', 'r2', 'r3', 'r4']: + router_compare_json_output(rname, "show mpls ldp binding json", "show_ldp_binding.ref") + +# Memory leak test template +def test_memory_leak(): + "Run the memory leak test and report results." + tgen = get_topogen() + if not tgen.is_memleak_enabled(): + pytest.skip('Memory leak test/report is disabled') + + tgen.report_memory_leaks() + +if __name__ == '__main__': + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/ldp-oc-topo1/r1/ldpd.conf b/tests/topotests/ldp-oc-topo1/r1/ldpd.conf new file mode 100644 index 000000000..2a8e02383 --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r1/ldpd.conf @@ -0,0 +1,24 @@ +hostname r1 +log file ldpd.log +! +debug mpls ldp zebra +debug mpls ldp event +debug mpls ldp errors +debug mpls ldp messages recv +debug mpls ldp messages sent +debug mpls ldp discovery hello recv +debug mpls ldp discovery hello sent +! +mpls ldp + router-id 1.1.1.1 + ordered-control + ! + address-family ipv4 + discovery transport-address 1.1.1.1 + ! + interface r1-eth0 + ! + ! +! +line vty +! diff --git a/tests/topotests/ldp-oc-topo1/r1/ospfd.conf b/tests/topotests/ldp-oc-topo1/r1/ospfd.conf new file mode 100644 index 000000000..6daf034d1 --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r1/ospfd.conf @@ -0,0 +1,7 @@ +hostname r1 +log file ospfd.log +! +router ospf + router-id 1.1.1.1 + network 0.0.0.0/0 area 0 +! diff --git a/tests/topotests/ldp-oc-topo1/r1/show_ip_ospf_neighbor.json b/tests/topotests/ldp-oc-topo1/r1/show_ip_ospf_neighbor.json new file mode 100644 index 000000000..2c493173f --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r1/show_ip_ospf_neighbor.json @@ -0,0 +1,12 @@ +{ + "neighbors":{ + "2.2.2.2":[ + { + "priority":1, + "state":"Full\/DR", + "address":"10.0.1.2", + "ifaceName":"r1-eth0:10.0.1.1" + } + ] + } +} diff --git a/tests/topotests/ldp-oc-topo1/r1/show_ip_route.ref b/tests/topotests/ldp-oc-topo1/r1/show_ip_route.ref new file mode 100644 index 000000000..d75b8f21d --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r1/show_ip_route.ref @@ -0,0 +1,171 @@ +{ + "1.1.1.1/32":[ + { + "prefix":"1.1.1.1/32", + "protocol":"ospf", + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":1, + "interfaceName":"lo", + "active":true + } + ] + }, + { + "prefix":"1.1.1.1/32", + "protocol":"connected", + "selected":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":1, + "interfaceName":"lo", + "active":true + } + ] + } + ], + "2.2.2.2/32":[ + { + "prefix":"2.2.2.2/32", + "protocol":"ospf", + "selected":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.1.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r1-eth0", + "active":true + } + ] + } + ], + "3.3.3.3/32":[ + { + "prefix":"3.3.3.3/32", + "protocol":"ospf", + "selected":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.1.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r1-eth0", + "active":true + } + ] + } + ], + "4.4.4.4/32":[ + { + "prefix":"4.4.4.4/32", + "protocol":"ospf", + "selected":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.1.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r1-eth0", + "active":true + } + ] + } + ], + "10.0.1.0/24":[ + { + "prefix":"10.0.1.0/24", + "protocol":"ospf", + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r1-eth0", + "active":true + } + ] + }, + { + "prefix":"10.0.1.0/24", + "protocol":"connected", + "selected":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r1-eth0", + "active":true + } + ] + } + ], + "10.0.2.0/24":[ + { + "prefix":"10.0.2.0/24", + "protocol":"ospf", + "selected":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.1.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r1-eth0", + "active":true + } + ] + } + ], + "10.0.3.0/24":[ + { + "prefix":"10.0.3.0/24", + "protocol":"ospf", + "selected":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.1.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r1-eth0", + "active":true + } + ] + } + ], + "123.0.1.0/24":[ + { + "prefix":"123.0.1.0/24", + "protocol":"ospf", + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r1-eth0", + "active":true + } + ] + }, + { + "prefix":"123.0.1.0/24", + "protocol":"connected", + "selected":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r1-eth0", + "active":true + } + ] + } + ] +} diff --git a/tests/topotests/ldp-oc-topo1/r1/show_ldp_binding.ref b/tests/topotests/ldp-oc-topo1/r1/show_ldp_binding.ref new file mode 100644 index 000000000..99a59668f --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r1/show_ldp_binding.ref @@ -0,0 +1,61 @@ +{ + "bindings":[ + { + "addressFamily":"ipv4", + "prefix":"1.1.1.1/32", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"2.2.2.2/32", + "neighborId":"2.2.2.2", + "remoteLabel":"imp-null", + "inUse":1 + }, + { + "addressFamily":"ipv4", + "prefix":"3.3.3.3/32", + "neighborId":"2.2.2.2", + "inUse":1 + }, + { + "addressFamily":"ipv4", + "prefix":"4.4.4.4/32", + "neighborId":"0.0.0.0", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.1.0/24", + "neighborId":"2.2.2.2", + "localLabel":"imp-null", + "remoteLabel":"imp-null", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.2.0/24", + "neighborId":"2.2.2.2", + "remoteLabel":"imp-null", + "inUse":1 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.3.0/24", + "neighborId":"2.2.2.2", + "inUse":1 + }, + { + "addressFamily":"ipv4", + "prefix":"123.0.1.0/24", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + } + ] +} diff --git a/tests/topotests/ldp-oc-topo1/r1/show_ldp_discovery.ref b/tests/topotests/ldp-oc-topo1/r1/show_ldp_discovery.ref new file mode 100644 index 000000000..b349f4418 --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r1/show_ldp_discovery.ref @@ -0,0 +1,11 @@ +{ + "adjacencies":[ + { + "addressFamily":"ipv4", + "neighborId":"2.2.2.2", + "type":"link", + "interface":"r1-eth0", + "helloHoldtime":15 + } + ] +} diff --git a/tests/topotests/ldp-oc-topo1/r1/show_ldp_neighbor.ref b/tests/topotests/ldp-oc-topo1/r1/show_ldp_neighbor.ref new file mode 100644 index 000000000..4bff444a4 --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r1/show_ldp_neighbor.ref @@ -0,0 +1,10 @@ +{ + "neighbors":[ + { + "addressFamily":"ipv4", + "neighborId":"2.2.2.2", + "state":"OPERATIONAL", + "transportAddress":"2.2.2.2" + } + ] +} diff --git a/tests/topotests/ldp-oc-topo1/r1/zebra.conf b/tests/topotests/ldp-oc-topo1/r1/zebra.conf new file mode 100644 index 000000000..83aea46e6 --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r1/zebra.conf @@ -0,0 +1,17 @@ +log file zebra.log +! +hostname r1 +! +interface lo + ip address 1.1.1.1/32 +! +interface r1-eth0 + description to sw0 + ip address 10.0.1.1/24 + ip address 123.0.1.1/24 +! +ip forwarding +! +! +line vty +! diff --git a/tests/topotests/ldp-oc-topo1/r2/ldpd.conf b/tests/topotests/ldp-oc-topo1/r2/ldpd.conf new file mode 100644 index 000000000..e1a552c70 --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r2/ldpd.conf @@ -0,0 +1,28 @@ +hostname r2 +log file ldpd.log +! +debug mpls ldp zebra +debug mpls ldp event +debug mpls ldp errors +debug mpls ldp messages recv +debug mpls ldp messages sent +debug mpls ldp discovery hello recv +debug mpls ldp discovery hello sent +! +mpls ldp + router-id 2.2.2.2 + ordered-control + ! + address-family ipv4 + discovery transport-address 2.2.2.2 + ! + interface r2-eth0 + ! + interface r2-eth1 + ! + interface r2-eth2 + ! + ! +! +line vty +! diff --git a/tests/topotests/ldp-oc-topo1/r2/ospfd.conf b/tests/topotests/ldp-oc-topo1/r2/ospfd.conf new file mode 100644 index 000000000..867881366 --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r2/ospfd.conf @@ -0,0 +1,7 @@ +hostname r2 +log file ospfd.log +! +router ospf + router-id 2.2.2.2 + network 0.0.0.0/0 area 0 +! diff --git a/tests/topotests/ldp-oc-topo1/r2/show_ip_ospf_neighbor.json b/tests/topotests/ldp-oc-topo1/r2/show_ip_ospf_neighbor.json new file mode 100644 index 000000000..55f12359e --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r2/show_ip_ospf_neighbor.json @@ -0,0 +1,31 @@ +{ + "neighbors":{ + "1.1.1.1":[ + { + "priority":1, + "state":"Full\/Backup", + "address":"10.0.1.1", + "ifaceName":"r2-eth0:10.0.1.2", + "retransmitCounter":0, + "requestCounter":0, + "dbSummaryCounter":0 + } + ], + "3.3.3.3":[ + { + "priority":1, + "state":"Full\/Backup", + "address":"10.0.2.3", + "ifaceName":"r2-eth1:10.0.2.2" + } + ], + "4.4.4.4":[ + { + "priority":1, + "state":"Full\/DR", + "address":"10.0.2.4", + "ifaceName":"r2-eth1:10.0.2.2" + } + ] + } +} diff --git a/tests/topotests/ldp-oc-topo1/r2/show_ip_route.ref b/tests/topotests/ldp-oc-topo1/r2/show_ip_route.ref new file mode 100644 index 000000000..060c0b429 --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r2/show_ip_route.ref @@ -0,0 +1,209 @@ +{ + "1.1.1.1/32":[ + { + "prefix":"1.1.1.1/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":10, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.1.1", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r2-eth0", + "active":true + } + ] + } + ], + "2.2.2.2/32":[ + { + "prefix":"2.2.2.2/32", + "protocol":"ospf", + "distance":110, + "metric":0, + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":1, + "interfaceName":"lo", + "active":true + } + ] + }, + { + "prefix":"2.2.2.2/32", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":1, + "interfaceName":"lo", + "active":true + } + ] + } + ], + "3.3.3.3/32":[ + { + "prefix":"3.3.3.3/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":10, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.3", + "afi":"ipv4", + "interfaceIndex":3, + "interfaceName":"r2-eth1", + "active":true + } + ] + } + ], + "4.4.4.4/32":[ + { + "prefix":"4.4.4.4/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":10, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.4", + "afi":"ipv4", + "interfaceIndex":3, + "interfaceName":"r2-eth1", + "active":true + } + ] + } + ], + "10.0.1.0\/24":[ + { + "prefix":"10.0.1.0\/24", + "protocol":"ospf", + "distance":110, + "metric":10, + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r2-eth0", + "active":true + } + ] + }, + { + "prefix":"10.0.1.0\/24", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r2-eth0", + "active":true + } + ] + } + ], + "10.0.2.0\/24":[ + { + "prefix":"10.0.2.0\/24", + "protocol":"ospf", + "distance":110, + "metric":10, + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":3, + "interfaceName":"r2-eth1", + "active":true + } + ] + }, + { + "prefix":"10.0.2.0\/24", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":3, + "interfaceName":"r2-eth1", + "active":true + } + ] + } + ], + "10.0.3.0\/24":[ + { + "prefix":"10.0.3.0\/24", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":20, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.3", + "afi":"ipv4", + "interfaceIndex":3, + "interfaceName":"r2-eth1", + "active":true + } + ] + } + ], + "123.0.1.0\/24":[ + { + "prefix":"123.0.1.0\/24", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":20, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.1.1", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r2-eth0", + "active":true + } + ] + } + ] +} diff --git a/tests/topotests/ldp-oc-topo1/r2/show_ldp_binding.ref b/tests/topotests/ldp-oc-topo1/r2/show_ldp_binding.ref new file mode 100644 index 000000000..95fb847c1 --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r2/show_ldp_binding.ref @@ -0,0 +1,63 @@ +{ + "bindings":[ + { + "addressFamily":"ipv4", + "prefix":"1.1.1.1/32", + "neighborId":"1.1.1.1", + "remoteLabel":"imp-null", + "inUse":1 + }, + { + "addressFamily":"ipv4", + "prefix":"2.2.2.2/32", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"3.3.3.3/32", + "neighborId":"3.3.3.3", + "remoteLabel":"imp-null", + "inUse":1 + }, + { + "addressFamily":"ipv4", + "prefix":"4.4.4.4/32", + "neighborId":"0.0.0.0", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.1.0/24", + "neighborId":"1.1.1.1", + "localLabel":"imp-null", + "remoteLabel":"imp-null", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.2.0/24", + "neighborId":"3.3.3.3", + "localLabel":"imp-null", + "remoteLabel":"imp-null", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.3.0/24", + "neighborId":"3.3.3.3", + "remoteLabel":"imp-null", + "inUse":1 + }, + { + "addressFamily":"ipv4", + "prefix":"123.0.1.0/24", + "neighborId":"1.1.1.1", + "remoteLabel":"imp-null", + "inUse":1 + } + ] +} diff --git a/tests/topotests/ldp-oc-topo1/r2/show_ldp_discovery.ref b/tests/topotests/ldp-oc-topo1/r2/show_ldp_discovery.ref new file mode 100644 index 000000000..812957008 --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r2/show_ldp_discovery.ref @@ -0,0 +1,18 @@ +{ + "adjacencies":[ + { + "addressFamily":"ipv4", + "neighborId":"1.1.1.1", + "type":"link", + "interface":"r2-eth0", + "helloHoldtime":15 + }, + { + "addressFamily":"ipv4", + "neighborId":"3.3.3.3", + "type":"link", + "interface":"r2-eth1", + "helloHoldtime":15 + } + ] +} diff --git a/tests/topotests/ldp-oc-topo1/r2/show_ldp_neighbor.ref b/tests/topotests/ldp-oc-topo1/r2/show_ldp_neighbor.ref new file mode 100644 index 000000000..eed35289e --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r2/show_ldp_neighbor.ref @@ -0,0 +1,16 @@ +{ + "neighbors":[ + { + "addressFamily":"ipv4", + "neighborId":"1.1.1.1", + "state":"OPERATIONAL", + "transportAddress":"1.1.1.1" + }, + { + "addressFamily":"ipv4", + "neighborId":"3.3.3.3", + "state":"OPERATIONAL", + "transportAddress":"3.3.3.3" + } + ] +} diff --git a/tests/topotests/ldp-oc-topo1/r2/zebra.conf b/tests/topotests/ldp-oc-topo1/r2/zebra.conf new file mode 100644 index 000000000..1f1e3e391 --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r2/zebra.conf @@ -0,0 +1,27 @@ +log file zebra.log +! +hostname r2 +! +interface lo + ip address 2.2.2.2/32 +! +interface r2-eth0 + description to sw0 + ip address 10.0.1.2/24 +! no link-detect +! +interface r2-eth1 + description to sw1 + ip address 10.0.2.2/24 +! no link-detect +! +interface r2-eths2 + description to sw2 + ip address 10.0.3.2/24 +! no link-detect +! +ip forwarding +! +! +line vty +! diff --git a/tests/topotests/ldp-oc-topo1/r3/ldpd.conf b/tests/topotests/ldp-oc-topo1/r3/ldpd.conf new file mode 100644 index 000000000..4e66b140a --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r3/ldpd.conf @@ -0,0 +1,24 @@ +hostname r3 +log file ldpd.log +! +debug mpls ldp zebra +debug mpls ldp event +debug mpls ldp errors +debug mpls ldp messages recv +debug mpls ldp messages sent +debug mpls ldp discovery hello recv +debug mpls ldp discovery hello sent +! +mpls ldp + router-id 3.3.3.3 + ordered-control + ! + address-family ipv4 + discovery transport-address 3.3.3.3 + ! + interface r3-eth0 + ! + ! +! +line vty +! diff --git a/tests/topotests/ldp-oc-topo1/r3/ospfd.conf b/tests/topotests/ldp-oc-topo1/r3/ospfd.conf new file mode 100644 index 000000000..202be238e --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r3/ospfd.conf @@ -0,0 +1,8 @@ +hostname r3 +password 1 +log file ospfd.log +! +router ospf + router-id 3.3.3.3 + network 0.0.0.0/0 area 0 +! diff --git a/tests/topotests/ldp-oc-topo1/r3/show_ip_ospf_neighbor.json b/tests/topotests/ldp-oc-topo1/r3/show_ip_ospf_neighbor.json new file mode 100644 index 000000000..24502ed81 --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r3/show_ip_ospf_neighbor.json @@ -0,0 +1,20 @@ +{ + "neighbors":{ + "2.2.2.2":[ + { + "priority":1, + "state":"Full\/DROther", + "address":"10.0.2.2", + "ifaceName":"r3-eth0:10.0.2.3" + } + ], + "4.4.4.4":[ + { + "priority":1, + "state":"Full\/DR", + "address":"10.0.2.4", + "ifaceName":"r3-eth0:10.0.2.3" + } + ] + } +} diff --git a/tests/topotests/ldp-oc-topo1/r3/show_ip_route.ref b/tests/topotests/ldp-oc-topo1/r3/show_ip_route.ref new file mode 100644 index 000000000..40800762b --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r3/show_ip_route.ref @@ -0,0 +1,209 @@ +{ + "1.1.1.1/32":[ + { + "prefix":"1.1.1.1/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":20, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r3-eth0", + "active":true + } + ] + } + ], + "2.2.2.2/32":[ + { + "prefix":"2.2.2.2/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":10, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r3-eth0", + "active":true + } + ] + } + ], + "3.3.3.3/32":[ + { + "prefix":"3.3.3.3/32", + "protocol":"ospf", + "distance":110, + "metric":0, + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":1, + "interfaceName":"lo", + "active":true + } + ] + }, + { + "prefix":"3.3.3.3/32", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":1, + "interfaceName":"lo", + "active":true + } + ] + } + ], + "4.4.4.4/32":[ + { + "prefix":"4.4.4.4/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":10, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.4", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r3-eth0", + "active":true + } + ] + } + ], + "10.0.1.0\/24":[ + { + "prefix":"10.0.1.0\/24", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":20, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r3-eth0", + "active":true + } + ] + } + ], + "10.0.2.0\/24":[ + { + "prefix":"10.0.2.0\/24", + "protocol":"ospf", + "distance":110, + "metric":10, + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r3-eth0", + "active":true + } + ] + }, + { + "prefix":"10.0.2.0\/24", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r3-eth0", + "active":true + } + ] + } + ], + "10.0.3.0\/24":[ + { + "prefix":"10.0.3.0\/24", + "protocol":"ospf", + "distance":110, + "metric":10, + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":3, + "interfaceName":"r3-eth1", + "active":true + } + ] + }, + { + "prefix":"10.0.3.0\/24", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":3, + "interfaceName":"r3-eth1", + "active":true + } + ] + } + ], + "123.0.1.0\/24":[ + { + "prefix":"123.0.1.0\/24", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":30, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r3-eth0", + "active":true + } + ] + } + ] +} diff --git a/tests/topotests/ldp-oc-topo1/r3/show_ldp_binding.ref b/tests/topotests/ldp-oc-topo1/r3/show_ldp_binding.ref new file mode 100644 index 000000000..100dd307e --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r3/show_ldp_binding.ref @@ -0,0 +1,61 @@ +{ + "bindings":[ + { + "addressFamily":"ipv4", + "prefix":"1.1.1.1/32", + "neighborId":"2.2.2.2", + "inUse":1 + }, + { + "addressFamily":"ipv4", + "prefix":"2.2.2.2/32", + "neighborId":"2.2.2.2", + "remoteLabel":"imp-null", + "inUse":1 + }, + { + "addressFamily":"ipv4", + "prefix":"3.3.3.3/32", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"4.4.4.4/32", + "neighborId":"0.0.0.0", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.1.0/24", + "neighborId":"2.2.2.2", + "remoteLabel":"imp-null", + "inUse":1 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.2.0/24", + "neighborId":"2.2.2.2", + "localLabel":"imp-null", + "remoteLabel":"imp-null", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.3.0/24", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"123.0.1.0/24", + "neighborId":"2.2.2.2", + "inUse":1 + } + ] +} diff --git a/tests/topotests/ldp-oc-topo1/r3/show_ldp_discovery.ref b/tests/topotests/ldp-oc-topo1/r3/show_ldp_discovery.ref new file mode 100644 index 000000000..c3a07e7e3 --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r3/show_ldp_discovery.ref @@ -0,0 +1,11 @@ +{ + "adjacencies":[ + { + "addressFamily":"ipv4", + "neighborId":"2.2.2.2", + "type":"link", + "interface":"r3-eth0", + "helloHoldtime":15 + } + ] +} diff --git a/tests/topotests/ldp-oc-topo1/r3/show_ldp_neighbor.ref b/tests/topotests/ldp-oc-topo1/r3/show_ldp_neighbor.ref new file mode 100644 index 000000000..4bff444a4 --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r3/show_ldp_neighbor.ref @@ -0,0 +1,10 @@ +{ + "neighbors":[ + { + "addressFamily":"ipv4", + "neighborId":"2.2.2.2", + "state":"OPERATIONAL", + "transportAddress":"2.2.2.2" + } + ] +} diff --git a/tests/topotests/ldp-oc-topo1/r3/zebra.conf b/tests/topotests/ldp-oc-topo1/r3/zebra.conf new file mode 100644 index 000000000..234c215dd --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r3/zebra.conf @@ -0,0 +1,22 @@ +log file zebra.log +! +hostname r3 +! +interface lo + ip address 3.3.3.3/32 +! +interface r3-eth0 + description to sw1 + ip address 10.0.2.3/24 +! no link-detect +! +interface r3-eth1 + description to sw2 + ip address 10.0.3.3/24 +! no link-detect +! +ip forwarding +! +! +line vty +! diff --git a/tests/topotests/ldp-oc-topo1/r4/ldpd.conf b/tests/topotests/ldp-oc-topo1/r4/ldpd.conf new file mode 100644 index 000000000..6b7d28f98 --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r4/ldpd.conf @@ -0,0 +1,24 @@ +hostname r4 +log file ldpd.log +! +debug mpls ldp zebra +debug mpls ldp event +debug mpls ldp errors +debug mpls ldp messages recv +debug mpls ldp messages sent +debug mpls ldp discovery hello recv +debug mpls ldp discovery hello sent +! +mpls ldp + router-id 4.4.4.4 + ordered-control + ! + address-family ipv4 + discovery transport-address 4.4.4.4 + ! + !interface r4-eth0 + ! + ! +! +line vty +! diff --git a/tests/topotests/ldp-oc-topo1/r4/ospfd.conf b/tests/topotests/ldp-oc-topo1/r4/ospfd.conf new file mode 100644 index 000000000..569dbc54e --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r4/ospfd.conf @@ -0,0 +1,7 @@ +hostname r4 +log file ospfd.log +! +router ospf + router-id 4.4.4.4 + network 0.0.0.0/0 area 0 +! diff --git a/tests/topotests/ldp-oc-topo1/r4/show_ip_ospf_neighbor.json b/tests/topotests/ldp-oc-topo1/r4/show_ip_ospf_neighbor.json new file mode 100644 index 000000000..794410522 --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r4/show_ip_ospf_neighbor.json @@ -0,0 +1,21 @@ + +{ + "neighbors":{ + "2.2.2.2":[ + { + "priority":1, + "state":"Full\/DROther", + "address":"10.0.2.2", + "ifaceName":"r4-eth0:10.0.2.4" + } + ], + "3.3.3.3":[ + { + "priority":1, + "state":"Full\/Backup", + "address":"10.0.2.3", + "ifaceName":"r4-eth0:10.0.2.4" + } + ] + } +} diff --git a/tests/topotests/ldp-oc-topo1/r4/show_ip_route.ref b/tests/topotests/ldp-oc-topo1/r4/show_ip_route.ref new file mode 100644 index 000000000..c9b83a1c7 --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r4/show_ip_route.ref @@ -0,0 +1,196 @@ +{ + "1.1.1.1/32":[ + { + "prefix":"1.1.1.1/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":20, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r4-eth0", + "active":true + } + ] + } + ], + "2.2.2.2/32":[ + { + "prefix":"2.2.2.2/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":10, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r4-eth0", + "active":true + } + ] + } + ], + "3.3.3.3/32":[ + { + "prefix":"3.3.3.3/32", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":10, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.3", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r4-eth0", + "active":true + } + ] + } + ], + "4.4.4.4/32":[ + { + "prefix":"4.4.4.4/32", + "protocol":"ospf", + "distance":110, + "metric":0, + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":1, + "interfaceName":"lo", + "active":true + } + ] + }, + { + "prefix":"4.4.4.4/32", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":1, + "interfaceName":"lo", + "active":true + } + ] + } + ], + "10.0.1.0\/24":[ + { + "prefix":"10.0.1.0\/24", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":20, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r4-eth0", + "active":true + } + ] + } + ], + "10.0.2.0\/24":[ + { + "prefix":"10.0.2.0\/24", + "protocol":"ospf", + "distance":110, + "metric":10, + "nexthops":[ + { + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r4-eth0", + "active":true + } + ] + }, + { + "prefix":"10.0.2.0\/24", + "protocol":"connected", + "selected":true, + "destSelected":true, + "distance":0, + "metric":0, + "installed":true, + "nexthops":[ + { + "fib":true, + "directlyConnected":true, + "interfaceIndex":2, + "interfaceName":"r4-eth0", + "active":true + } + ] + } + ], + "10.0.3.0\/24":[ + { + "prefix":"10.0.3.0\/24", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":20, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.3", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r4-eth0", + "active":true + } + ] + } + ], + "123.0.1.0\/24":[ + { + "prefix":"123.0.1.0\/24", + "protocol":"ospf", + "selected":true, + "destSelected":true, + "distance":110, + "metric":30, + "installed":true, + "nexthops":[ + { + "fib":true, + "ip":"10.0.2.2", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r4-eth0", + "active":true + } + ] + } + ] +} diff --git a/tests/topotests/ldp-oc-topo1/r4/show_ldp_binding.ref b/tests/topotests/ldp-oc-topo1/r4/show_ldp_binding.ref new file mode 100644 index 000000000..2a46c4034 --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r4/show_ldp_binding.ref @@ -0,0 +1,68 @@ +{ + "bindings":[ + { + "addressFamily":"ipv4", + "prefix":"1.1.1.1/32", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"2.2.2.2/32", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"3.3.3.3/32", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"4.4.4.4/32", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.1.0/24", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.2.0/24", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"10.0.3.0/24", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + }, + { + "addressFamily":"ipv4", + "prefix":"123.0.1.0/24", + "neighborId":"0.0.0.0", + "localLabel":"imp-null", + "remoteLabel":"-", + "inUse":0 + } + ] +} diff --git a/tests/topotests/ldp-oc-topo1/r4/show_ldp_discovery.ref b/tests/topotests/ldp-oc-topo1/r4/show_ldp_discovery.ref new file mode 100644 index 000000000..2c63c0851 --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r4/show_ldp_discovery.ref @@ -0,0 +1,2 @@ +{ +} diff --git a/tests/topotests/ldp-oc-topo1/r4/show_ldp_neighbor.ref b/tests/topotests/ldp-oc-topo1/r4/show_ldp_neighbor.ref new file mode 100644 index 000000000..2c63c0851 --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r4/show_ldp_neighbor.ref @@ -0,0 +1,2 @@ +{ +} diff --git a/tests/topotests/ldp-oc-topo1/r4/zebra.conf b/tests/topotests/ldp-oc-topo1/r4/zebra.conf new file mode 100644 index 000000000..7e291053e --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/r4/zebra.conf @@ -0,0 +1,17 @@ +log file zebra.log +! +hostname r4 +! +interface lo + ip address 4.4.4.4/32 +! +interface r4-eth0 + description to sw1 + ip address 10.0.2.4/24 +! no link-detect +! +ip forwarding +! +! +line vty +! diff --git a/tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.dot b/tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.dot new file mode 100644 index 000000000..62058e3cb --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.dot @@ -0,0 +1,76 @@ +## Color coding: +######################### +## Main FRR: #f08080 red +## Switches: #d0e0d0 gray +## RIP: #19e3d9 Cyan +## RIPng: #fcb314 dark yellow +## OSPFv2: #32b835 Green +## OSPFv3: #19e3d9 Cyan +## ISIS IPv4 #fcb314 dark yellow +## ISIS IPv6 #9a81ec purple +## BGP IPv4 #eee3d3 beige +## BGP IPv6 #fdff00 yellow +##### Colors (see http://www.color-hex.com/) + +graph template { + label="Test Topology - LDP-OC 1"; + + # Routers + r1 [ + shape=doubleoctagon, + label="r1", + fillcolor="#f08080", + style=filled, + ]; + r2 [ + shape=doubleoctagon + label="r2", + fillcolor="#f08080", + style=filled, + ]; + r3 [ + shape=doubleoctagon + label="r3", + fillcolor="#f08080", + style=filled, + ]; + r4 [ + shape=doubleoctagon + label="r4", + fillcolor="#f08080", + style=filled, + ]; + + + # Switches + s0 [ + shape=oval, + label="10.0.1.0/24", + fillcolor="#d0e0d0", + style=filled, + ]; + s1 [ + shape=oval, + label="10.0.2.0/24", + fillcolor="#d0e0d0", + style=filled, + ]; + s2 [ + shape=oval, + label="10.0.3.0/24", + fillcolor="#d0e0d0", + style=filled, + ]; + + # Connections + + r1 -- s0 [label="eth0"]; + r2 -- s0 [label="eth0"]; + + r2 -- s1 [label="eth1"]; + r3 -- s1 [label="eth0"]; + r4 -- s1 [label="eth0"]; + + r2 -- s2 [label="eth2"]; + r3 -- s2 [label="eth1"]; +} diff --git a/tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.py b/tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.py new file mode 100755 index 000000000..eda1b37e5 --- /dev/null +++ b/tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.py @@ -0,0 +1,227 @@ +#!/usr/bin/env python + +# +# test_ldp_oc_topo1.py +# Part of NetDEF Topology Tests +# +# Copyright (c) 2020 by by Volta Networks +# +# 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_ldp_oc_topo1.py: Simple FRR/Quagga LDP Test + + +---------+ + | r1 | + | 1.1.1.1 | + +----+----+ + | .1 r1-eth0 + | + ~~~~~~~~~~~~~ + ~~ sw0 ~~ + ~~ 10.0.1.0/24 ~~ + ~~~~~~~~~~~~~ + |10.0.1.0/24 + | + | .2 r2-eth0 + +----+----+ + | r2 | + | 2.2.2.2 | + +--+---+--+ + r2-eth2 .2 | | .2 r2-eth1 + ______/ \______ + / \ + ~~~~~~~~~~~~~ ~~~~~~~~~~~~~ +~~ sw2 ~~ ~~ sw1 ~~ +~~ 10.0.3.0/24 ~~ ~~ 10.0.2.0/24 ~~ + ~~~~~~~~~~~~~ ~~~~~~~~~~~~~ + | / | + \ _________/ | + \ / \ +r3-eth1 .3 | | .3 r3-eth0 | .4 r4-eth0 + +----+--+---+ +----+----+ + | r3 | | r4 | + | 3.3.3.3 | | 4.4.4.4 | + +-----------+ +---------+ +""" + +import os +import sys +import pytest +import json +from time import sleep +from functools import partial + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, '../')) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger + +# Required to instantiate the topology builder class. +from mininet.topo import Topo + +class TemplateTopo(Topo): + "Test topology builder" + def build(self, *_args, **_opts): + "Build function" + tgen = get_topogen(self) + + # + # Define FRR Routers + # + for router in ['r1', 'r2', 'r3', 'r4']: + tgen.add_router(router) + + # + # Define connections + # + switch = tgen.add_switch('s0') + switch.add_link(tgen.gears['r1']) + switch.add_link(tgen.gears['r2']) + + switch = tgen.add_switch('s1') + switch.add_link(tgen.gears['r2']) + switch.add_link(tgen.gears['r3']) + switch.add_link(tgen.gears['r4']) + + switch = tgen.add_switch('s2') + switch.add_link(tgen.gears['r2']) + switch.add_link(tgen.gears['r3']) + +def setup_module(mod): + "Sets up the pytest environment" + tgen = Topogen(TemplateTopo, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + # For all registered routers, load the zebra configuration file + for rname, router in router_list.iteritems(): + router.load_config( + TopoRouter.RD_ZEBRA, + os.path.join(CWD, '{}/zebra.conf'.format(rname)) + ) + # Don't start ospfd and ldpd in the CE nodes + if router.name[0] == 'r': + router.load_config( + TopoRouter.RD_OSPF, + os.path.join(CWD, '{}/ospfd.conf'.format(rname)) + ) + router.load_config( + TopoRouter.RD_LDP, + os.path.join(CWD, '{}/ldpd.conf'.format(rname)) + ) + + tgen.start_router() + +def teardown_module(mod): + "Teardown the pytest environment" + tgen = get_topogen() + + # This function tears down the whole topology. + tgen.stop_topology() + + +def router_compare_json_output(rname, command, reference): + "Compare router JSON output" + + logger.info('Comparing router "%s" "%s" output', rname, command) + + tgen = get_topogen() + filename = '{}/{}/{}'.format(CWD, rname, reference) + expected = json.loads(open(filename).read()) + + # Run test function until we get an result. Wait at most 80 seconds. + test_func = partial(topotest.router_json_cmp, + tgen.gears[rname], command, expected) + _, diff = topotest.run_and_expect(test_func, None, count=160, wait=0.5) + + assertmsg = '"{}" JSON output mismatches the expected result'.format(rname) + assert diff is None, assertmsg + +def test_ospf_convergence(): + logger.info("Test: check OSPF adjacencies") + + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + for rname in ['r1', 'r2', 'r3', 'r4']: + router_compare_json_output(rname, "show ip ospf neighbor json", "show_ip_ospf_neighbor.json") + +def test_rib(): + logger.info("Test: verify RIB") + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + for rname in ['r1', 'r2', 'r3', 'r4']: + router_compare_json_output(rname, "show ip route json", "show_ip_route.ref") + +def test_ldp_adjacencies(): + logger.info("Test: verify LDP adjacencies") + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + for rname in ['r1', 'r2', 'r3', 'r4']: + router_compare_json_output(rname, "show mpls ldp discovery json", "show_ldp_discovery.ref") + +def test_ldp_neighbors(): + logger.info("Test: verify LDP neighbors") + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + for rname in ['r1', 'r2', 'r3', 'r4']: + router_compare_json_output(rname, "show mpls ldp neighbor json", "show_ldp_neighbor.ref") + +def test_ldp_bindings(): + logger.info("Test: verify LDP bindings") + tgen = get_topogen() + + # Skip if previous fatal error condition is raised + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + for rname in ['r1', 'r2', 'r3', 'r4']: + router_compare_json_output(rname, "show mpls ldp binding json", "show_ldp_binding.ref") + +# Memory leak test template +def test_memory_leak(): + "Run the memory leak test and report results." + tgen = get_topogen() + if not tgen.is_memleak_enabled(): + pytest.skip('Memory leak test/report is disabled') + + tgen.report_memory_leaks() + +if __name__ == '__main__': + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/ldp-topo1/r1/ip_mpls_route.ref b/tests/topotests/ldp-topo1/r1/ip_mpls_route.ref index f244122f1..a13c1d459 100644 --- a/tests/topotests/ldp-topo1/r1/ip_mpls_route.ref +++ b/tests/topotests/ldp-topo1/r1/ip_mpls_route.ref @@ -3,3 +3,4 @@ xx as to xx via inet 10.0.1.2 dev r1-eth0 proto xx xx via inet 10.0.1.2 dev r1-eth0 proto xx xx via inet 10.0.1.2 dev r1-eth0 proto xx xx via inet 10.0.1.2 dev r1-eth0 proto xx + diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py index f3c17be68..997b72d69 100644 --- a/tests/topotests/lib/bgp.py +++ b/tests/topotests/lib/bgp.py @@ -382,8 +382,8 @@ def __create_bgp_neighbor(topo, input_dict, router, addr_type, add_neigh=True): disable_connected = peer.setdefault("disable_connected_check", False) - keep_alive = peer.setdefault("keep_alive", 60) - hold_down = peer.setdefault("hold_down", 180) + keep_alive = peer.setdefault("keepalivetimer", 60) + hold_down = peer.setdefault("holddowntimer", 180) password = peer.setdefault("password", None) max_hop_limit = peer.setdefault("ebgp_multihop", 1) diff --git a/tests/topotests/ospf6-topo1/test_ospf6_topo1.py b/tests/topotests/ospf6-topo1/test_ospf6_topo1.py index cb0c4af22..2f7a4ce4e 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 cec765699..f64a46deb 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 b0a25f12a..e43041758 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 000000000..f94ee9993 --- /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 000000000..8e58e8c66 --- /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 3f1b4d65c..6e35c9797 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 0e0569e23..9101d7e03 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 000000000..f86fe70be --- /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 5951c7e28..dab144919 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 d1148061b..80cc18a57 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 e40bf45f5..2f675e2d5 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/zapi_msg.c b/zebra/zapi_msg.c index 88e3ce68d..f1c181438 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -2418,9 +2418,11 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS) } if (!(zpr.rule.filter.dst_ip.family == AF_INET || zpr.rule.filter.dst_ip.family == AF_INET6)) { - zlog_warn("Unsupported PBR IP family: %s (%" PRIu8 ")", - family2str(zpr.rule.filter.dst_ip.family), - zpr.rule.filter.dst_ip.family); + zlog_warn( + "Unsupported PBR destination IP family: %s (%" PRIu8 + ")", + family2str(zpr.rule.filter.dst_ip.family), + zpr.rule.filter.dst_ip.family); return; } @@ -2512,14 +2514,18 @@ static inline void zread_ipset_entry(ZAPI_HANDLER_ARGS) if (!(zpi.dst.family == AF_INET || zpi.dst.family == AF_INET6)) { - zlog_warn("Unsupported PBR IP family: %s (%" PRIu8 ")", - family2str(zpi.dst.family), zpi.dst.family); + zlog_warn( + "Unsupported PBR destination IP family: %s (%" PRIu8 + ")", + family2str(zpi.dst.family), zpi.dst.family); goto stream_failure; } if (!(zpi.src.family == AF_INET || zpi.src.family == AF_INET6)) { - zlog_warn("Unsupported PBR IP family: %s (%" PRIu8 ")", - family2str(zpi.src.family), zpi.src.family); + zlog_warn( + "Unsupported PBR source IP family: %s (%" PRIu8 + ")", + family2str(zpi.src.family), zpi.src.family); goto stream_failure; } diff --git a/zebra/zebra_mlag.c b/zebra/zebra_mlag.c index cf2fe2648..8ba7998f5 100644 --- a/zebra/zebra_mlag.c +++ b/zebra/zebra_mlag.c @@ -322,7 +322,7 @@ static int zebra_mlag_post_data_from_main_thread(struct thread *thread) STREAM_GETL(s, msg_type); if (IS_ZEBRA_DEBUG_MLAG) zlog_debug( - "%s: Posting MLAG data for msg_type:0x%x to interested cleints", + "%s: Posting MLAG data for msg_type:0x%x to interested clients", __func__, msg_type); msg_len = s->endp - ZEBRA_MLAG_METADATA_LEN; @@ -364,7 +364,7 @@ stream_failure: /* * Start the MLAG Thread, this will be used to write client data on to - * MLAG Process and to read the data from MLAG and post to cleints. + * MLAG Process and to read the data from MLAG and post to clients. * when all clients are un-registered, this Thread will be * suspended. */ diff --git a/zebra/zebra_ptm_redistribute.c b/zebra/zebra_ptm_redistribute.c index 01d5114b9..eabc2e005 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 6cfc68eb7..c758e2583 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 2963d8382..500c2c84a 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 6a630e1ac..56e805ea0 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/zebra_vty.c b/zebra/zebra_vty.c index 79ce43be9..ccc6e9e46 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -241,25 +241,13 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn, vty_out(vty, "\n"); time_t uptime; - struct tm tm; uptime = monotime(NULL); uptime -= re->uptime; - gmtime_r(&uptime, &tm); - vty_out(vty, " Last update "); + frrtime_to_interval(uptime, buf, sizeof(buf)); - if (uptime < ONE_DAY_SECOND) - vty_out(vty, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min, - tm.tm_sec); - else if (uptime < ONE_WEEK_SECOND) - vty_out(vty, "%dd%02dh%02dm", tm.tm_yday, tm.tm_hour, - tm.tm_min); - else - vty_out(vty, "%02dw%dd%02dh", tm.tm_yday / 7, - tm.tm_yday - ((tm.tm_yday / 7) * 7), - tm.tm_hour); - vty_out(vty, " ago\n"); + vty_out(vty, " Last update %s ago\n", buf); if (show_ng) vty_out(vty, " Nexthop Group ID: %u\n", re->nhe_id); @@ -402,14 +390,15 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, json_object *json_route = NULL; json_object *json_labels = NULL; time_t uptime; - struct tm tm; struct vrf *vrf = NULL; rib_dest_t *dest = rib_dest_from_rnode(rn); struct nexthop_group *nhg; + char up_str[MONOTIME_STRLEN]; uptime = monotime(NULL); uptime -= re->uptime; - gmtime_r(&uptime, &tm); + + frrtime_to_interval(uptime, up_str, sizeof(up_str)); /* If showing fib information, use the fib view of the * nexthops. @@ -474,18 +463,8 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, json_object_int_add(json_route, "internalNextHopActiveNum", nexthop_group_active_nexthop_num( &(re->nhe->nhg))); - if (uptime < ONE_DAY_SECOND) - sprintf(buf, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min, - tm.tm_sec); - else if (uptime < ONE_WEEK_SECOND) - sprintf(buf, "%dd%02dh%02dm", tm.tm_yday, tm.tm_hour, - tm.tm_min); - else - sprintf(buf, "%02dw%dd%02dh", tm.tm_yday / 7, - tm.tm_yday - ((tm.tm_yday / 7) * 7), - tm.tm_hour); - json_object_string_add(json_route, "uptime", buf); + json_object_string_add(json_route, "uptime", up_str); for (ALL_NEXTHOPS_PTR(nhg, nexthop)) { json_nexthop = json_object_new_object(); @@ -774,17 +753,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, sizeof(buf), 1)); } - if (uptime < ONE_DAY_SECOND) - vty_out(vty, ", %02d:%02d:%02d", tm.tm_hour, - tm.tm_min, tm.tm_sec); - else if (uptime < ONE_WEEK_SECOND) - vty_out(vty, ", %dd%02dh%02dm", tm.tm_yday, - tm.tm_hour, tm.tm_min); - else - vty_out(vty, ", %02dw%dd%02dh", tm.tm_yday / 7, - tm.tm_yday - ((tm.tm_yday / 7) * 7), - tm.tm_hour); - vty_out(vty, "\n"); + vty_out(vty, ", %s\n", up_str); } } diff --git a/zebra/zserv.c b/zebra/zserv.c index 40aa9010c..7f806d82c 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -858,7 +858,6 @@ void zserv_event(struct zserv *client, enum zserv_event event) #define ZEBRA_TIME_BUF 32 static char *zserv_time_buf(time_t *time1, char *buf, int buflen) { - struct tm tm; time_t now; assert(buf != NULL); @@ -872,17 +871,9 @@ static char *zserv_time_buf(time_t *time1, char *buf, int buflen) now = monotime(NULL); now -= *time1; - gmtime_r(&now, &tm); - - if (now < ONE_DAY_SECOND) - snprintf(buf, buflen, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min, - tm.tm_sec); - else if (now < ONE_WEEK_SECOND) - snprintf(buf, buflen, "%dd%02dh%02dm", tm.tm_yday, tm.tm_hour, - tm.tm_min); - else - snprintf(buf, buflen, "%02dw%dd%02dh", tm.tm_yday / 7, - tm.tm_yday - ((tm.tm_yday / 7) * 7), tm.tm_hour); + + frrtime_to_interval(now, buf, buflen); + return buf; } @@ -1001,8 +992,6 @@ static void zebra_show_stale_client_detail(struct vty *vty, struct zserv *client) { char buf[PREFIX2STR_BUFFER]; - struct tm tm; - struct timeval tv; time_t uptime; struct client_gr_info *info = NULL; struct zserv *s = NULL; @@ -1028,26 +1017,13 @@ static void zebra_show_stale_client_detail(struct vty *vty, if (ZEBRA_CLIENT_GR_ENABLED(info->capabilities)) { if (info->stale_client_ptr) { s = (struct zserv *)(info->stale_client_ptr); - uptime = monotime(&tv); + uptime = monotime(NULL); uptime -= s->restart_time; - gmtime_r(&uptime, &tm); - - vty_out(vty, "Last restart time : "); - if (uptime < ONE_DAY_SECOND) - vty_out(vty, "%02d:%02d:%02d", - tm.tm_hour, tm.tm_min, - tm.tm_sec); - else if (uptime < ONE_WEEK_SECOND) - vty_out(vty, "%dd%02dh%02dm", - tm.tm_yday, tm.tm_hour, - tm.tm_min); - else - vty_out(vty, "%02dw%dd%02dh", - tm.tm_yday / 7, - tm.tm_yday - ((tm.tm_yday / 7) - * 7), - tm.tm_hour); - vty_out(vty, " ago\n"); + + frrtime_to_interval(uptime, buf, sizeof(buf)); + + vty_out(vty, "Last restart time : %s ago\n", + buf); vty_out(vty, "Stalepath removal time: %d sec\n", info->stale_removal_time); diff --git a/zebra/zserv.h b/zebra/zserv.h index 6a075cc9a..6ab7fbd91 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. |