diff options
118 files changed, 3025 insertions, 2150 deletions
diff --git a/babeld/babel_interface.c b/babeld/babel_interface.c index ae8b161b01..d37e0b608f 100644 --- a/babeld/babel_interface.c +++ b/babeld/babel_interface.c @@ -187,6 +187,7 @@ babel_interface_address_delete (ZAPI_CALLBACK_ARGS) send_request(ifc->ifp, NULL, 0); send_update(ifc->ifp, 0, NULL, 0); + connected_free(&ifc); return 0; } diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c index 64dda0033b..90e2df2367 100644 --- a/bfdd/ptm_adapter.c +++ b/bfdd/ptm_adapter.c @@ -816,7 +816,10 @@ static int bfdd_interface_address_update(ZAPI_CALLBACK_ARGS) : "delete", ifc->address); - bfdd_sessions_enable_address(ifc); + if (cmd == ZEBRA_INTERFACE_ADDRESS_ADD) + bfdd_sessions_enable_address(ifc); + else + connected_free(&ifc); return 0; } diff --git a/bgpd/bgp_addpath.c b/bgpd/bgp_addpath.c index d07d41bef8..d822f6e330 100644 --- a/bgpd/bgp_addpath.c +++ b/bgpd/bgp_addpath.c @@ -80,14 +80,12 @@ void bgp_addpath_init_bgp_data(struct bgp_addpath_bgp_data *d) afi_t afi; int i; - for (afi = AFI_IP; afi < AFI_MAX; afi++) { - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { - for (i = 0; i < BGP_ADDPATH_MAX; i++) { - d->id_allocators[afi][safi][i] = NULL; - d->peercount[afi][safi][i] = 0; - } - d->total_peercount[afi][safi] = 0; + FOREACH_AFI_SAFI (afi, safi) { + for (i = 0; i < BGP_ADDPATH_MAX; i++) { + d->id_allocators[afi][safi][i] = NULL; + d->peercount[afi][safi][i] = 0; } + d->total_peercount[afi][safi] = 0; } } diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index b94e24e870..ce22e8404d 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -257,9 +257,12 @@ void bgp_attr_flush_encap(struct attr *attr) attr->encap_subtlvs = NULL; } #ifdef ENABLE_BGP_VNC - if (attr->vnc_subtlvs) { - encap_free(attr->vnc_subtlvs); - attr->vnc_subtlvs = NULL; + struct bgp_attr_encap_subtlv *vnc_subtlvs = + bgp_attr_get_vnc_subtlvs(attr); + + if (vnc_subtlvs) { + encap_free(vnc_subtlvs); + bgp_attr_set_vnc_subtlvs(attr, NULL); } #endif } @@ -403,7 +406,9 @@ static bool overlay_index_same(const struct attr *a1, const struct attr *a2) return false; if (!a1 && !a2) return true; - return !memcmp(&(a1->evpn_overlay), &(a2->evpn_overlay), + + return !memcmp(bgp_attr_get_evpn_overlay(a1), + bgp_attr_get_evpn_overlay(a2), sizeof(struct bgp_route_evpn)); } @@ -663,17 +668,19 @@ unsigned int attrhash_key_make(const void *p) MIX(lcommunity_hash_make(attr->lcommunity)); if (attr->ecommunity) MIX(ecommunity_hash_make(attr->ecommunity)); - if (attr->ipv6_ecommunity) - MIX(ecommunity_hash_make(attr->ipv6_ecommunity)); - if (attr->cluster) - MIX(cluster_hash_key_make(attr->cluster)); - if (attr->transit) - MIX(transit_hash_key_make(attr->transit)); + if (bgp_attr_get_ipv6_ecommunity(attr)) + MIX(ecommunity_hash_make(bgp_attr_get_ipv6_ecommunity(attr))); + if (bgp_attr_get_cluster(attr)) + MIX(cluster_hash_key_make(bgp_attr_get_cluster(attr))); + if (bgp_attr_get_transit(attr)) + MIX(transit_hash_key_make(bgp_attr_get_transit(attr))); if (attr->encap_subtlvs) MIX(encap_hash_key_make(attr->encap_subtlvs)); #ifdef ENABLE_BGP_VNC - if (attr->vnc_subtlvs) - MIX(encap_hash_key_make(attr->vnc_subtlvs)); + struct bgp_attr_encap_subtlv *vnc_subtlvs = + bgp_attr_get_vnc_subtlvs(attr); + if (vnc_subtlvs) + MIX(encap_hash_key_make(vnc_subtlvs)); #endif MIX(attr->mp_nexthop_len); key = jhash(attr->mp_nexthop_global.s6_addr, IPV6_MAX_BYTELEN, key); @@ -703,15 +710,19 @@ bool attrhash_cmp(const void *p1, const void *p2) && attr1->label_index == attr2->label_index && attr1->mp_nexthop_len == attr2->mp_nexthop_len && attr1->ecommunity == attr2->ecommunity - && attr1->ipv6_ecommunity == attr2->ipv6_ecommunity + && bgp_attr_get_ipv6_ecommunity(attr1) + == bgp_attr_get_ipv6_ecommunity(attr2) && attr1->lcommunity == attr2->lcommunity - && attr1->cluster == attr2->cluster - && attr1->transit == attr2->transit + && bgp_attr_get_cluster(attr1) + == bgp_attr_get_cluster(attr2) + && bgp_attr_get_transit(attr1) + == bgp_attr_get_transit(attr2) && attr1->rmap_table_id == attr2->rmap_table_id && (attr1->encap_tunneltype == attr2->encap_tunneltype) && encap_same(attr1->encap_subtlvs, attr2->encap_subtlvs) #ifdef ENABLE_BGP_VNC - && encap_same(attr1->vnc_subtlvs, attr2->vnc_subtlvs) + && encap_same(bgp_attr_get_vnc_subtlvs(attr1), + bgp_attr_get_vnc_subtlvs(attr2)) #endif && IPV6_ADDR_SAME(&attr1->mp_nexthop_global, &attr2->mp_nexthop_global) @@ -797,9 +808,11 @@ static void *bgp_attr_hash_alloc(void *p) val->encap_subtlvs = NULL; } #ifdef ENABLE_BGP_VNC - if (val->vnc_subtlvs) { - val->vnc_subtlvs = NULL; - } + struct bgp_attr_encap_subtlv *vnc_subtlvs = + bgp_attr_get_vnc_subtlvs(val); + + if (vnc_subtlvs) + bgp_attr_set_vnc_subtlvs(val, NULL); #endif if (val->srv6_l3vpn) val->srv6_l3vpn = NULL; @@ -814,6 +827,7 @@ static void *bgp_attr_hash_alloc(void *p) struct attr *bgp_attr_intern(struct attr *attr) { struct attr *find; + struct ecommunity *ecomm; /* Intern referenced strucutre. */ if (attr->aspath) { @@ -836,12 +850,13 @@ struct attr *bgp_attr_intern(struct attr *attr) attr->ecommunity->refcnt++; } - if (attr->ipv6_ecommunity) { - if (!attr->ipv6_ecommunity->refcnt) - attr->ipv6_ecommunity = - ecommunity_intern(attr->ipv6_ecommunity); + ecomm = bgp_attr_get_ipv6_ecommunity(attr); + if (ecomm) { + if (!ecomm->refcnt) + bgp_attr_set_ipv6_ecommunity(attr, + ecommunity_intern(ecomm)); else - attr->ipv6_ecommunity->refcnt++; + ecomm->refcnt++; } if (attr->lcommunity) { @@ -850,17 +865,23 @@ struct attr *bgp_attr_intern(struct attr *attr) else attr->lcommunity->refcnt++; } - if (attr->cluster) { - if (!attr->cluster->refcnt) - attr->cluster = cluster_intern(attr->cluster); + + struct cluster_list *cluster = bgp_attr_get_cluster(attr); + + if (cluster) { + if (!cluster->refcnt) + bgp_attr_set_cluster(attr, cluster_intern(cluster)); else - attr->cluster->refcnt++; + cluster->refcnt++; } - if (attr->transit) { - if (!attr->transit->refcnt) - attr->transit = transit_intern(attr->transit); + + struct transit *transit = bgp_attr_get_transit(attr); + + if (transit) { + if (!transit->refcnt) + bgp_attr_set_transit(attr, transit_intern(transit)); else - attr->transit->refcnt++; + transit->refcnt++; } if (attr->encap_subtlvs) { if (!attr->encap_subtlvs->refcnt) @@ -882,12 +903,16 @@ struct attr *bgp_attr_intern(struct attr *attr) attr->srv6_vpn->refcnt++; } #ifdef ENABLE_BGP_VNC - if (attr->vnc_subtlvs) { - if (!attr->vnc_subtlvs->refcnt) - attr->vnc_subtlvs = encap_intern(attr->vnc_subtlvs, - VNC_SUBTLV_TYPE); + struct bgp_attr_encap_subtlv *vnc_subtlvs = + bgp_attr_get_vnc_subtlvs(attr); + + if (vnc_subtlvs) { + if (!vnc_subtlvs->refcnt) + bgp_attr_set_vnc_subtlvs( + attr, + encap_intern(vnc_subtlvs, VNC_SUBTLV_TYPE)); else - attr->vnc_subtlvs->refcnt++; + vnc_subtlvs->refcnt++; } #endif @@ -1003,8 +1028,7 @@ struct attr *bgp_attr_aggregate_intern( SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE); - ret = route_map_apply(aggregate->rmap.map, p, RMAP_BGP, - &rmap_path); + ret = route_map_apply(aggregate->rmap.map, p, &rmap_path); bgp->peer_self->rmap_type = 0; @@ -1036,6 +1060,9 @@ struct attr *bgp_attr_aggregate_intern( /* Unintern just the sub-components of the attr, but not the attr */ void bgp_attr_unintern_sub(struct attr *attr) { + struct ecommunity *ecomm; + struct cluster_list *cluster; + /* aspath refcount shoud be decrement. */ if (attr->aspath) aspath_unintern(&attr->aspath); @@ -1045,31 +1072,43 @@ void bgp_attr_unintern_sub(struct attr *attr) community_unintern(&attr->community); UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)); - if (attr->ecommunity) - ecommunity_unintern(&attr->ecommunity); + ecommunity_unintern(&attr->ecommunity); UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)); - if (attr->ipv6_ecommunity) - ecommunity_unintern(&attr->ipv6_ecommunity); + ecomm = bgp_attr_get_ipv6_ecommunity(attr); + ecommunity_unintern(&ecomm); UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES)); + bgp_attr_set_ipv6_ecommunity(attr, NULL); if (attr->lcommunity) lcommunity_unintern(&attr->lcommunity); UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)); - if (attr->cluster) - cluster_unintern(&attr->cluster); + cluster = bgp_attr_get_cluster(attr); + if (cluster) { + cluster_unintern(&cluster); + bgp_attr_set_cluster(attr, cluster); + } UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)); - if (attr->transit) - transit_unintern(&attr->transit); + struct transit *transit = bgp_attr_get_transit(attr); + + if (transit) { + transit_unintern(&transit); + bgp_attr_set_transit(attr, transit); + } if (attr->encap_subtlvs) encap_unintern(&attr->encap_subtlvs, ENCAP_SUBTLV_TYPE); #ifdef ENABLE_BGP_VNC - if (attr->vnc_subtlvs) - encap_unintern(&attr->vnc_subtlvs, VNC_SUBTLV_TYPE); + struct bgp_attr_encap_subtlv *vnc_subtlvs = + bgp_attr_get_vnc_subtlvs(attr); + + if (vnc_subtlvs) { + encap_unintern(&vnc_subtlvs, VNC_SUBTLV_TYPE); + bgp_attr_set_vnc_subtlvs(attr, vnc_subtlvs); + } #endif if (attr->srv6_l3vpn) @@ -1129,6 +1168,9 @@ void bgp_attr_unintern(struct attr **pattr) void bgp_attr_flush(struct attr *attr) { + struct ecommunity *ecomm; + struct cluster_list *cluster; + if (attr->aspath && !attr->aspath->refcnt) { aspath_free(attr->aspath); attr->aspath = NULL; @@ -1137,26 +1179,36 @@ void bgp_attr_flush(struct attr *attr) community_free(&attr->community); if (attr->ecommunity && !attr->ecommunity->refcnt) ecommunity_free(&attr->ecommunity); - if (attr->ipv6_ecommunity && !attr->ipv6_ecommunity->refcnt) - ecommunity_free(&attr->ipv6_ecommunity); + ecomm = bgp_attr_get_ipv6_ecommunity(attr); + if (ecomm && !ecomm->refcnt) + ecommunity_free(&ecomm); + bgp_attr_set_ipv6_ecommunity(attr, NULL); if (attr->lcommunity && !attr->lcommunity->refcnt) lcommunity_free(&attr->lcommunity); - if (attr->cluster && !attr->cluster->refcnt) { - cluster_free(attr->cluster); - attr->cluster = NULL; + + cluster = bgp_attr_get_cluster(attr); + if (cluster && !cluster->refcnt) { + cluster_free(cluster); + bgp_attr_set_cluster(attr, NULL); } - if (attr->transit && !attr->transit->refcnt) { - transit_free(attr->transit); - attr->transit = NULL; + + struct transit *transit = bgp_attr_get_transit(attr); + + if (transit && !transit->refcnt) { + transit_free(transit); + bgp_attr_set_transit(attr, NULL); } if (attr->encap_subtlvs && !attr->encap_subtlvs->refcnt) { encap_free(attr->encap_subtlvs); attr->encap_subtlvs = NULL; } #ifdef ENABLE_BGP_VNC - if (attr->vnc_subtlvs && !attr->vnc_subtlvs->refcnt) { - encap_free(attr->vnc_subtlvs); - attr->vnc_subtlvs = NULL; + struct bgp_attr_encap_subtlv *vnc_subtlvs = + bgp_attr_get_vnc_subtlvs(attr); + + if (vnc_subtlvs && !vnc_subtlvs->refcnt) { + encap_free(vnc_subtlvs); + bgp_attr_set_vnc_subtlvs(attr, NULL); } #endif } @@ -1929,8 +1981,9 @@ bgp_attr_cluster_list(struct bgp_attr_parser_args *args) args->total); } - attr->cluster = - cluster_parse((struct in_addr *)stream_pnt(peer->curr), length); + bgp_attr_set_cluster( + attr, cluster_parse((struct in_addr *)stream_pnt(peer->curr), + length)); /* XXX: Fix cluster_parse to use stream API and then remove this */ stream_forward_getp(peer->curr, length); @@ -2302,19 +2355,21 @@ bgp_attr_ipv6_ext_communities(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; + struct ecommunity *ipv6_ecomm = NULL; if (length == 0) { - attr->ipv6_ecommunity = NULL; + bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm); return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, args->total); } - attr->ipv6_ecommunity = - ecommunity_parse_ipv6(stream_pnt(peer->curr), length); + ipv6_ecomm = ecommunity_parse_ipv6(stream_pnt(peer->curr), length); + bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm); + /* XXX: fix ecommunity_parse to use stream API */ stream_forward_getp(peer->curr, length); - if (!attr->ipv6_ecommunity) + if (!ipv6_ecomm) return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, args->total); @@ -2419,15 +2474,17 @@ static int bgp_attr_encap(uint8_t type, struct peer *peer, /* IN */ #ifdef ENABLE_BGP_VNC } else { struct bgp_attr_encap_subtlv *stlv_last; - for (stlv_last = attr->vnc_subtlvs; + struct bgp_attr_encap_subtlv *vnc_subtlvs = + bgp_attr_get_vnc_subtlvs(attr); + + for (stlv_last = vnc_subtlvs; stlv_last && stlv_last->next; stlv_last = stlv_last->next) ; - if (stlv_last) { + if (stlv_last) stlv_last->next = tlv; - } else { - attr->vnc_subtlvs = tlv; - } + else + bgp_attr_set_vnc_subtlvs(attr, tlv); #endif } } @@ -2787,7 +2844,7 @@ bgp_attr_pmsi_tunnel(struct bgp_attr_parser_args *args) } attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL); - attr->pmsi_tnl_type = tnl_type; + bgp_attr_set_pmsi_tnl_type(attr, tnl_type); stream_get(&attr->label, peer->curr, BGP_LABEL_BYTES); /* Forward read pointer of input stream. */ @@ -2837,10 +2894,9 @@ static bgp_attr_parse_ret_t bgp_attr_unknown(struct bgp_attr_parser_args *args) SET_FLAG(*startp, BGP_ATTR_FLAG_PARTIAL); /* Store transitive attribute to the end of attr->transit. */ - if (!attr->transit) - attr->transit = XCALLOC(MTYPE_TRANSIT, sizeof(struct transit)); - - transit = attr->transit; + transit = bgp_attr_get_transit(attr); + if (!transit) + transit = XCALLOC(MTYPE_TRANSIT, sizeof(struct transit)); if (transit->val) transit->val = XREALLOC(MTYPE_TRANSIT_VAL, transit->val, @@ -2850,6 +2906,7 @@ static bgp_attr_parse_ret_t bgp_attr_unknown(struct bgp_attr_parser_args *args) memcpy(transit->val + transit->length, startp, total); transit->length += total; + bgp_attr_set_transit(attr, transit); return BGP_ATTR_PARSE_PROCEED; } @@ -2922,6 +2979,7 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr, struct aspath *as4_path = NULL; as_t as4_aggregator = 0; struct in_addr as4_aggregator_addr = {.s_addr = 0}; + struct transit *transit; /* Initialize bitmap. */ memset(seen, 0, BGP_ATTR_BITMAP_SIZE); @@ -3287,35 +3345,44 @@ done: aspath_unintern(&as4_path); } + transit = bgp_attr_get_transit(attr); if (ret != BGP_ATTR_PARSE_ERROR) { /* Finally intern unknown attribute. */ - if (attr->transit) - attr->transit = transit_intern(attr->transit); + if (transit) + bgp_attr_set_transit(attr, transit_intern(transit)); if (attr->encap_subtlvs) attr->encap_subtlvs = encap_intern(attr->encap_subtlvs, ENCAP_SUBTLV_TYPE); #ifdef ENABLE_BGP_VNC - if (attr->vnc_subtlvs) - attr->vnc_subtlvs = encap_intern(attr->vnc_subtlvs, - VNC_SUBTLV_TYPE); + struct bgp_attr_encap_subtlv *vnc_subtlvs = + bgp_attr_get_vnc_subtlvs(attr); + + if (vnc_subtlvs) + bgp_attr_set_vnc_subtlvs( + attr, + encap_intern(vnc_subtlvs, VNC_SUBTLV_TYPE)); #endif } else { - if (attr->transit) { - transit_free(attr->transit); - attr->transit = NULL; + if (transit) { + transit_free(transit); + bgp_attr_set_transit(attr, NULL); } bgp_attr_flush_encap(attr); }; /* Sanity checks */ - if (attr->transit) - assert(attr->transit->refcnt > 0); + transit = bgp_attr_get_transit(attr); + if (transit) + assert(transit->refcnt > 0); if (attr->encap_subtlvs) assert(attr->encap_subtlvs->refcnt > 0); #ifdef ENABLE_BGP_VNC - if (attr->vnc_subtlvs) - assert(attr->vnc_subtlvs->refcnt > 0); + struct bgp_attr_encap_subtlv *vnc_subtlvs = + bgp_attr_get_vnc_subtlvs(attr); + + if (vnc_subtlvs) + assert(vnc_subtlvs->refcnt > 0); #endif return ret; @@ -3567,7 +3634,7 @@ static void bgp_packet_mpattr_tea(struct bgp *bgp, struct peer *peer, #ifdef ENABLE_BGP_VNC_ATTR case BGP_ATTR_VNC: attrname = "VNC"; - subtlvs = attr->vnc_subtlvs; + subtlvs = bgp_attr_get_vnc_subtlvs(attr); if (subtlvs == NULL) /* nothing to do */ return; attrlenfield = 0; /* no outer T + L */ @@ -3893,6 +3960,8 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, /* Route Reflector. */ if (peer->sort == BGP_PEER_IBGP && from && from->sort == BGP_PEER_IBGP) { + struct cluster_list *cluster = bgp_attr_get_cluster(attr); + /* Originator ID. */ stream_putc(s, BGP_ATTR_FLAG_OPTIONAL); stream_putc(s, BGP_ATTR_ORIGINATOR_ID); @@ -3907,16 +3976,15 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, stream_putc(s, BGP_ATTR_FLAG_OPTIONAL); stream_putc(s, BGP_ATTR_CLUSTER_LIST); - if (attr->cluster) { - stream_putc(s, attr->cluster->length + 4); + if (cluster) { + stream_putc(s, cluster->length + 4); /* If this peer configuration's parent BGP has * cluster_id. */ if (bgp->config & BGP_CONFIG_CLUSTER_ID) stream_put_in_addr(s, &bgp->cluster_id); else stream_put_in_addr(s, &bgp->router_id); - stream_put(s, attr->cluster->list, - attr->cluster->length); + stream_put(s, cluster->list, cluster->length); } else { stream_putc(s, 4); /* If this peer configuration's parent BGP has @@ -4112,7 +4180,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, stream_putc(s, BGP_ATTR_PMSI_TUNNEL); stream_putc(s, 9); // Length stream_putc(s, 0); // Flags - stream_putc(s, attr->pmsi_tnl_type); + stream_putc(s, bgp_attr_get_pmsi_tnl_type(attr)); stream_put(s, &(attr->label), BGP_LABEL_BYTES); // MPLS Label / VXLAN VNI stream_put_ipv4(s, attr->nexthop.s_addr); @@ -4120,8 +4188,10 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer, } /* Unknown transit attribute. */ - if (attr->transit) - stream_put(s, attr->transit->val, attr->transit->length); + struct transit *transit = bgp_attr_get_transit(attr); + + if (transit) + stream_put(s, transit->val, transit->length); /* Return total size of attribute. */ return stream_get_endp(s) - cp; diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index ef0e74344a..1b176f8716 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -185,7 +185,7 @@ struct attr { struct lcommunity *lcommunity; /* Route-Reflector Cluster attribute */ - struct cluster_list *cluster; + struct cluster_list *cluster1; /* Unknown transitive attribute. */ struct transit *transit; @@ -331,7 +331,7 @@ struct transit { #define BGP_CLUSTER_LIST_LENGTH(attr) \ (((attr)->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) \ - ? (attr)->cluster->length \ + ? bgp_attr_get_cluster((attr))->length \ : 0) typedef enum { @@ -457,4 +457,81 @@ static inline uint32_t mac_mobility_seqnum(struct attr *attr) { return (attr) ? attr->mm_seqnum : 0; } + +static inline enum pta_type bgp_attr_get_pmsi_tnl_type(struct attr *attr) +{ + return attr->pmsi_tnl_type; +} + +static inline void bgp_attr_set_pmsi_tnl_type(struct attr *attr, + enum pta_type pmsi_tnl_type) +{ + attr->pmsi_tnl_type = pmsi_tnl_type; +} + +static inline struct ecommunity * +bgp_attr_get_ipv6_ecommunity(const struct attr *attr) +{ + return attr->ipv6_ecommunity; +} + +static inline void bgp_attr_set_ipv6_ecommunity(struct attr *attr, + struct ecommunity *ipv6_ecomm) +{ + attr->ipv6_ecommunity = ipv6_ecomm; +} + +static inline struct transit *bgp_attr_get_transit(const struct attr *attr) +{ + return attr->transit; +} + +static inline void bgp_attr_set_transit(struct attr *attr, + struct transit *transit) +{ + attr->transit = transit; +} + +static inline struct cluster_list *bgp_attr_get_cluster(const struct attr *attr) +{ + return attr->cluster1; +} + +static inline void bgp_attr_set_cluster(struct attr *attr, + struct cluster_list *cl) +{ + attr->cluster1 = cl; +} + +static inline const struct bgp_route_evpn * +bgp_attr_get_evpn_overlay(const struct attr *attr) +{ + return &attr->evpn_overlay; +} + +static inline void bgp_attr_set_evpn_overlay(struct attr *attr, + struct bgp_route_evpn *eo) +{ + memcpy(&attr->evpn_overlay, eo, sizeof(struct bgp_route_evpn)); +} + +static inline struct bgp_attr_encap_subtlv * +bgp_attr_get_vnc_subtlvs(const struct attr *attr) +{ +#ifdef ENABLE_BGP_VNC + return attr->vnc_subtlvs; +#else + return NULL; +#endif +} + +static inline void +bgp_attr_set_vnc_subtlvs(struct attr *attr, + struct bgp_attr_encap_subtlv *vnc_subtlvs) +{ +#ifdef ENABLE_BGP_VNC + attr->vnc_subtlvs = vnc_subtlvs; +#endif +} + #endif /* _QUAGGA_BGP_ATTR_H */ diff --git a/bgpd/bgp_conditional_adv.c b/bgpd/bgp_conditional_adv.c index 0731adcb84..b5cd1b52b7 100644 --- a/bgpd/bgp_conditional_adv.c +++ b/bgpd/bgp_conditional_adv.c @@ -47,10 +47,11 @@ bgp_check_rmap_prefixes_in_bgp_table(struct bgp_table *table, RESET_FLAG(dummy_attr.rmap_change_flags); - ret = route_map_apply(rmap, dest_p, RMAP_BGP, &path); + ret = route_map_apply(rmap, dest_p, &path); if (ret != RMAP_PERMITMATCH) bgp_attr_flush(&dummy_attr); else { + bgp_dest_unlock_node(dest); if (BGP_DEBUG(update, UPDATE_OUT)) zlog_debug( "%s: Condition map routes present in BGP table", @@ -112,7 +113,7 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi, RESET_FLAG(dummy_attr.rmap_change_flags); - if (route_map_apply(rmap, dest_p, RMAP_BGP, &path) + if (route_map_apply(rmap, dest_p, &path) != RMAP_PERMITMATCH) { bgp_attr_flush(&dummy_attr); continue; diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index c2c2d17a24..2c076fb80b 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -429,18 +429,21 @@ bool bgp_dump_attr(struct attr *attr, char *buf, size_t size) ", originator %pI4", &attr->originator_id); if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST))) { + struct cluster_list *cluster; int i; snprintf(buf + strlen(buf), size - strlen(buf), ", clusterlist"); - for (i = 0; i < attr->cluster->length / 4; i++) + + cluster = bgp_attr_get_cluster(attr); + for (i = 0; i < cluster->length / 4; i++) snprintfrr(buf + strlen(buf), size - strlen(buf), - " %pI4", &attr->cluster->list[i]); + " %pI4", &cluster->list[i]); } if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL))) snprintf(buf + strlen(buf), size - strlen(buf), - ", pmsi tnltype %u", attr->pmsi_tnl_type); + ", pmsi tnltype %u", bgp_attr_get_pmsi_tnl_type(attr)); if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))) snprintf(buf + strlen(buf), size - strlen(buf), ", path %s", diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index de3757aebb..74cbf3a80a 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -327,6 +327,9 @@ void ecommunity_unintern(struct ecommunity **ecom) { struct ecommunity *ret; + if (!*ecom) + return; + if ((*ecom)->refcnt) (*ecom)->refcnt--; diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h index e9c52287f1..6318e7edb1 100644 --- a/bgpd/bgp_ecommunity.h +++ b/bgpd/bgp_ecommunity.h @@ -227,7 +227,7 @@ extern struct ecommunity *ecommunity_merge(struct ecommunity *, extern struct ecommunity *ecommunity_uniq_sort(struct ecommunity *); extern struct ecommunity *ecommunity_intern(struct ecommunity *); extern bool ecommunity_cmp(const void *arg1, const void *arg2); -extern void ecommunity_unintern(struct ecommunity **); +extern void ecommunity_unintern(struct ecommunity **ecommunity); extern unsigned int ecommunity_hash_make(const void *); extern struct ecommunity *ecommunity_str2com(const char *, int, int); extern struct ecommunity *ecommunity_str2com_ipv6(const char *str, int type, diff --git a/bgpd/bgp_errors.c b/bgpd/bgp_errors.c index 8a33ce6789..0f9d5fc73a 100644 --- a/bgpd/bgp_errors.c +++ b/bgpd/bgp_errors.c @@ -463,6 +463,18 @@ static struct log_ref ferr_bgp_err[] = { .suggestion = "Change one of the two router-id's", }, { + .code = EC_BGP_INVALID_BGP_INSTANCE, + .title = "BGP instance for the specifc vrf is invalid", + .description = "Indicates that specified bgp instance is NULL", + .suggestion = "Get log files from router and open an issue", + }, + { + .code = EC_BGP_INVALID_ROUTE, + .title = "BGP route node is invalid", + .description = "BGP route for the specified AFI/SAFI is NULL", + .suggestion = "Get log files from router and open an issue", + }, + { .code = END_FERR, } }; diff --git a/bgpd/bgp_errors.h b/bgpd/bgp_errors.h index 49c58ae6b0..20056d382a 100644 --- a/bgpd/bgp_errors.h +++ b/bgpd/bgp_errors.h @@ -99,6 +99,8 @@ enum bgp_log_refs { EC_BGP_INVALID_NEXTHOP_LENGTH, EC_BGP_DOPPELGANGER_CONFIG, EC_BGP_ROUTER_ID_SAME, + EC_BGP_INVALID_BGP_INSTANCE, + EC_BGP_INVALID_ROUTE, }; extern void bgp_error_init(void); diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 67d0a95cb6..890f7963e6 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -980,7 +980,7 @@ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn, } else if (p->prefix.route_type == BGP_EVPN_AD_ROUTE) { ret = bgp_evpn_remote_es_evi_add(bgp, vpn, p); } else { - switch (pi->attr->pmsi_tnl_type) { + switch (bgp_attr_get_pmsi_tnl_type(pi->attr)) { case PMSI_TNLTYPE_INGR_REPL: flood_control = VXLAN_FLOOD_HEAD_END_REPL; break; @@ -1711,7 +1711,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, /* PMSI is only needed for type-3 routes */ if (p->prefix.route_type == BGP_EVPN_IMET_ROUTE) { attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL); - attr.pmsi_tnl_type = PMSI_TNLTYPE_INGR_REPL; + bgp_attr_set_pmsi_tnl_type(&attr, PMSI_TNLTYPE_INGR_REPL); } if (bgp_debug_zebra(NULL)) { @@ -2930,6 +2930,8 @@ static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install) evp, vrf_id_to_name( bgp_vrf->vrf_id)); + bgp_dest_unlock_node(rd_dest); + bgp_dest_unlock_node(dest); return ret; } } @@ -3009,6 +3011,9 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp, ? "MACIP" : "IMET", vpn->vni); + + bgp_dest_unlock_node(rd_dest); + bgp_dest_unlock_node(dest); return ret; } } @@ -3738,12 +3743,14 @@ static int process_type3_route(struct peer *peer, afi_t afi, safi_t safi, */ if (attr && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL))) { - if (attr->pmsi_tnl_type != PMSI_TNLTYPE_INGR_REPL && - attr->pmsi_tnl_type != PMSI_TNLTYPE_PIM_SM) { - flog_warn(EC_BGP_EVPN_PMSI_PRESENT, - "%u:%s - Rx EVPN Type-3 NLRI with unsupported PTA %d", - peer->bgp->vrf_id, peer->host, - attr->pmsi_tnl_type); + enum pta_type pmsi_tnl_type = bgp_attr_get_pmsi_tnl_type(attr); + + if (pmsi_tnl_type != PMSI_TNLTYPE_INGR_REPL + && pmsi_tnl_type != PMSI_TNLTYPE_PIM_SM) { + flog_warn( + EC_BGP_EVPN_PMSI_PRESENT, + "%u:%s - Rx EVPN Type-3 NLRI with unsupported PTA %d", + peer->bgp->vrf_id, peer->host, pmsi_tnl_type); } } @@ -3942,11 +3949,13 @@ static void evpn_mpattr_encode_type5(struct stream *s, const struct prefix *p, else stream_put(s, &p_evpn_p->prefix_addr.ip.ipaddr_v6, 16); if (attr) { + const struct bgp_route_evpn *evpn_overlay = + bgp_attr_get_evpn_overlay(attr); + if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip)) - stream_put_ipv4(s, - attr->evpn_overlay.gw_ip.ipv4.s_addr); + stream_put_ipv4(s, evpn_overlay->gw_ip.ipv4.s_addr); else - stream_put(s, &(attr->evpn_overlay.gw_ip.ipv6), 16); + stream_put(s, &(evpn_overlay->gw_ip.ipv6), 16); } else { if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip)) stream_put_ipv4(s, 0); @@ -4201,7 +4210,7 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi, bgp_vrf->adv_cmd_rmap[afi][safi] .map, bgp_dest_get_prefix(dest), - RMAP_BGP, &tmp_pi); + &tmp_pi); if (ret == RMAP_DENYMATCH) { bgp_attr_flush(&tmp_attr); continue; diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c index 021e811147..bf9a2f849a 100644 --- a/bgpd/bgp_evpn_mh.c +++ b/bgpd/bgp_evpn_mh.c @@ -763,6 +763,9 @@ static int bgp_evpn_type4_remote_routes_import(struct bgp *bgp, install ? "install" : "uninstall", evp, es->esi_str); + + bgp_dest_unlock_node(rd_dest); + bgp_dest_unlock_node(dest); return ret; } } diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c index 3b7fb649a9..57f212b05d 100644 --- a/bgpd/bgp_flowspec_vty.c +++ b/bgpd/bgp_flowspec_vty.c @@ -268,6 +268,7 @@ void route_vty_out_flowspec(struct vty *vty, const struct prefix *p, json_object *json_ecom_path = NULL; json_object *json_time_path = NULL; char timebuf[BGP_UPTIME_LEN]; + struct ecommunity *ipv6_ecomm = NULL; if (p == NULL || p->family != AF_FLOWSPEC) return; @@ -298,16 +299,19 @@ void route_vty_out_flowspec(struct vty *vty, const struct prefix *p, json_object_array_add(json_paths, json_nlri_path); if (!path) return; - if (path->attr && - (path->attr->ecommunity || path->attr->ipv6_ecommunity)) { + + if (path->attr) + ipv6_ecomm = bgp_attr_get_ipv6_ecommunity(path->attr); + + if (path->attr && (path->attr->ecommunity || ipv6_ecomm)) { /* Print attribute */ attr = path->attr; if (attr->ecommunity) s1 = ecommunity_ecom2str(attr->ecommunity, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); - if (attr->ipv6_ecommunity) - s2 = ecommunity_ecom2str(attr->ipv6_ecommunity, - ECOMMUNITY_FORMAT_ROUTE_MAP, 0); + if (ipv6_ecomm) + s2 = ecommunity_ecom2str( + ipv6_ecomm, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); if (!s1 && !s2) return; if (display == NLRI_STRING_FORMAT_LARGE) diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 4468408415..dd31a9b7cb 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -792,9 +792,13 @@ void bgp_adjust_routeadv(struct peer *peer) BGP_TIMER_OFF(peer->t_routeadv); peer->synctime = bgp_clock(); - thread_add_timer_msec(bm->master, bgp_generate_updgrp_packets, - peer, 0, - &peer->t_generate_updgrp_packets); + /* If suppress fib pending is enabled, route is advertised to + * peers when the status is received from the FIB. The delay + * is added to update group packet generate which will allow + * more routes to be sent in the update message + */ + BGP_UPDATE_GROUP_TIMER_ON(&peer->t_generate_updgrp_packets, + bgp_generate_updgrp_packets); return; } diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h index b9156df617..cd464d8c58 100644 --- a/bgpd/bgp_fsm.h +++ b/bgpd/bgp_fsm.h @@ -47,6 +47,18 @@ thread_cancel_event(bm->master, (P)); \ } while (0) +#define BGP_UPDATE_GROUP_TIMER_ON(T, F) \ + do { \ + if (BGP_SUPPRESS_FIB_ENABLED(peer->bgp) && \ + PEER_ROUTE_ADV_DELAY(peer)) \ + thread_add_timer_msec(bm->master, (F), peer, \ + (BGP_DEFAULT_UPDATE_ADVERTISEMENT_TIME * 1000),\ + T); \ + else \ + thread_add_timer_msec(bm->master, (F), peer, \ + 0, T); \ + } while (0) \ + #define BGP_MSEC_JITTER 10 /* Status codes for bgp_event_update() */ diff --git a/bgpd/bgp_io.c b/bgpd/bgp_io.c index 38455b5e02..53fd3b5fe3 100644 --- a/bgpd/bgp_io.c +++ b/bgpd/bgp_io.c @@ -149,12 +149,17 @@ static int bgp_process_writes(struct thread *thread) fatal = true; } + /* If suppress fib pending is enabled, route is advertised to peers when + * the status is received from the FIB. The delay is added + * to update group packet generate which will allow more routes to be + * sent in the update message + */ if (reschedule) { thread_add_write(fpt->master, bgp_process_writes, peer, peer->fd, &peer->t_write); } else if (!fatal) { - BGP_TIMER_ON(peer->t_generate_updgrp_packets, - bgp_generate_updgrp_packets, 0); + BGP_UPDATE_GROUP_TIMER_ON(&peer->t_generate_updgrp_packets, + bgp_generate_updgrp_packets); } return 0; diff --git a/bgpd/bgp_mac.c b/bgpd/bgp_mac.c index 265b4568e5..ec73ebb296 100644 --- a/bgpd/bgp_mac.c +++ b/bgpd/bgp_mac.c @@ -34,7 +34,7 @@ #include "bgpd/bgp_evpn_private.h" DEFINE_MTYPE_STATIC(BGPD, BSM, "Mac Hash Entry"); -DEFINE_MTYPE_STATIC(BGPD, BSM_STRING, "Mac Hash Entry Interface String"); +DEFINE_MTYPE_STATIC(BGPD, BSM_STRING, "Mac Hash Entry Intf String"); struct bgp_self_mac { struct ethaddr macaddr; @@ -156,7 +156,7 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer, struct prefix_rd prd; uint32_t num_labels = 0; mpls_label_t *label_pnt = NULL; - struct bgp_route_evpn evpn; + struct bgp_route_evpn *evpn; if (pevpn->family == AF_EVPN && pevpn->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE @@ -209,14 +209,15 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer, continue; } - memcpy(&evpn, &pi->attr->evpn_overlay, sizeof(evpn)); + memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr), + sizeof(evpn)); int32_t ret = bgp_update(peer, p, pi->addpath_rx_id, pi->attr, AFI_L2VPN, SAFI_EVPN, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, label_pnt, num_labels, - 1, &evpn); + 1, evpn); if (ret < 0) bgp_dest_unlock_node(dest); diff --git a/bgpd/bgp_memory.c b/bgpd/bgp_memory.c index 8bdab16680..d8fc98e048 100644 --- a/bgpd/bgp_memory.c +++ b/bgpd/bgp_memory.c @@ -116,7 +116,7 @@ DEFINE_MTYPE(BGPD, LCOMMUNITY_STR, "Large Community display string") DEFINE_MTYPE(BGPD, LCOMMUNITY_VAL, "Large Community value") DEFINE_MTYPE(BGPD, BGP_EVPN, "BGP EVPN Information") -DEFINE_MTYPE(BGPD, BGP_EVPN_MH_INFO, "BGP EVPN Multihoming Information") +DEFINE_MTYPE(BGPD, BGP_EVPN_MH_INFO, "BGP EVPN MH Information") DEFINE_MTYPE(BGPD, BGP_EVPN_ES_VTEP, "BGP EVPN ES VTEP") DEFINE_MTYPE(BGPD, BGP_EVPN_ES_EVI_VTEP, "BGP EVPN ES-EVI VTEP") DEFINE_MTYPE(BGPD, BGP_EVPN_ES, "BGP EVPN ESI Information") diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 0c527efb8c..662c5da414 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -265,7 +265,7 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr, if (STREAM_READABLE(data) != 0) { flog_err( EC_BGP_UPDATE_RCV, - "%s [Error] Update packet error / VPN (%td data remaining after parsing)", + "%s [Error] Update packet error / VPN (%zu data remaining after parsing)", peer->host, STREAM_READABLE(data)); return BGP_NLRI_PARSE_ERROR_PACKET_LENGTH; } @@ -744,7 +744,7 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ info.attr = &static_attr; ret = route_map_apply( bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_TOVPN], - p, RMAP_BGP, &info); + p, &info); if (RMAP_DENYMATCH == ret) { bgp_attr_flush(&static_attr); /* free any added parts */ if (debug) @@ -1190,7 +1190,7 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ info.extra = path_vpn->extra; /* Used for source-vrf filter */ ret = route_map_apply(bgp_vrf->vpn_policy[afi] .rmap[BGP_VPN_POLICY_DIR_FROMVPN], - p, RMAP_BGP, &info); + p, &info); if (RMAP_DENYMATCH == ret) { bgp_attr_flush(&static_attr); /* free any added parts */ if (debug) diff --git a/bgpd/bgp_nb_config.c b/bgpd/bgp_nb_config.c index eca7093fcd..ee6b13278d 100644 --- a/bgpd/bgp_nb_config.c +++ b/bgpd/bgp_nb_config.c @@ -173,7 +173,6 @@ int bgp_router_destroy(struct nb_cb_destroy_args *args) case NB_EV_APPLY: bgp = nb_running_unset_entry(args->dnode); - bgp_vpn_leak_unimport(bgp); bgp_delete(bgp); break; @@ -9080,10 +9079,10 @@ int bgp_global_afi_safis_afi_safi_ipv4_unicast_use_multiple_paths_ebgp_maximum_p switch (args->event) { case NB_EV_VALIDATE: maxpaths = yang_dnode_get_uint16(args->dnode, NULL); - if (maxpaths > MULTIPATH_NUM) { + if (maxpaths > multipath_num) { snprintf(args->errmsg, args->errmsg_len, "maxpaths %u is out of range %u", maxpaths, - MULTIPATH_NUM); + multipath_num); return NB_ERR_VALIDATION; } break; @@ -9151,10 +9150,10 @@ int bgp_global_afi_safis_afi_safi_ipv4_unicast_use_multiple_paths_ibgp_maximum_p switch (args->event) { case NB_EV_VALIDATE: maxpaths = yang_dnode_get_uint16(args->dnode, NULL); - if (maxpaths > MULTIPATH_NUM) { + if (maxpaths > multipath_num) { snprintf(args->errmsg, args->errmsg_len, "maxpaths %u is out of range %u", maxpaths, - MULTIPATH_NUM); + multipath_num); return NB_ERR_VALIDATION; } break; @@ -10998,10 +10997,10 @@ int bgp_global_afi_safis_afi_safi_ipv6_unicast_use_multiple_paths_ebgp_maximum_p switch (args->event) { case NB_EV_VALIDATE: maxpaths = yang_dnode_get_uint16(args->dnode, NULL); - if (maxpaths > MULTIPATH_NUM) { + if (maxpaths > multipath_num) { snprintf(args->errmsg, args->errmsg_len, "maxpaths %u is out of range %u", maxpaths, - MULTIPATH_NUM); + multipath_num); return NB_ERR_VALIDATION; } break; @@ -11760,10 +11759,10 @@ int bgp_global_afi_safis_afi_safi_ipv4_labeled_unicast_use_multiple_paths_ebgp_m switch (args->event) { case NB_EV_VALIDATE: maxpaths = yang_dnode_get_uint16(args->dnode, NULL); - if (maxpaths > MULTIPATH_NUM) { + if (maxpaths > multipath_num) { snprintf(args->errmsg, args->errmsg_len, "maxpaths %u is out of range %u", maxpaths, - MULTIPATH_NUM); + multipath_num); return NB_ERR_VALIDATION; } break; @@ -11998,10 +11997,10 @@ int bgp_global_afi_safis_afi_safi_ipv6_labeled_unicast_use_multiple_paths_ebgp_m switch (args->event) { case NB_EV_VALIDATE: maxpaths = yang_dnode_get_uint16(args->dnode, NULL); - if (maxpaths > MULTIPATH_NUM) { + if (maxpaths > multipath_num) { snprintf(args->errmsg, args->errmsg_len, "maxpaths %u is out of range %u", maxpaths, - MULTIPATH_NUM); + multipath_num); return NB_ERR_VALIDATION; } break; @@ -12028,10 +12027,10 @@ int bgp_global_afi_safis_afi_safi_ipv6_labeled_unicast_use_multiple_paths_ibgp_m switch (args->event) { case NB_EV_VALIDATE: maxpaths = yang_dnode_get_uint16(args->dnode, NULL); - if (maxpaths > MULTIPATH_NUM) { + if (maxpaths > multipath_num) { snprintf(args->errmsg, args->errmsg_len, "maxpaths %u is out of range %u", maxpaths, - MULTIPATH_NUM); + multipath_num); return NB_ERR_VALIDATION; } break; diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 29cca99fd7..1a9f59db64 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -45,7 +45,7 @@ #include "bgpd/bgp_vty.h" #include "bgpd/bgp_rd.h" -DEFINE_MTYPE_STATIC(BGPD, MARTIAN_STRING, "BGP Martian Address Intf String"); +DEFINE_MTYPE_STATIC(BGPD, MARTIAN_STRING, "BGP Martian Addr Intf String"); int bgp_nexthop_cache_compare(const struct bgp_nexthop_cache *a, const struct bgp_nexthop_cache *b) diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index a23acda0a8..3d73e34235 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -279,18 +279,17 @@ static void bgp_update_explicit_eors(struct peer *peer) if (bgp_debug_neighbor_events(peer)) zlog_debug("Peer %s: Checking explicit EORs", peer->host); - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { - if (peer->afc_nego[afi][safi] - && !CHECK_FLAG(peer->af_sflags[afi][safi], - PEER_STATUS_EOR_RECEIVED)) { - if (bgp_debug_neighbor_events(peer)) - zlog_debug( - " afi %d safi %d didn't receive EOR", - afi, safi); - return; - } + FOREACH_AFI_SAFI (afi, safi) { + if (peer->afc_nego[afi][safi] + && !CHECK_FLAG(peer->af_sflags[afi][safi], + PEER_STATUS_EOR_RECEIVED)) { + if (bgp_debug_neighbor_events(peer)) + zlog_debug( + " afi %d safi %d didn't receive EOR", + afi, safi); + return; } + } peer->update_delay_over = 1; peer->bgp->explicit_eors++; diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c index f7dd08443f..a3f1eb8401 100644 --- a/bgpd/bgp_pbr.c +++ b/bgpd/bgp_pbr.c @@ -915,10 +915,10 @@ int bgp_pbr_build_and_validate_entry(const struct prefix *p, api->action_num++; } } - if (path && path->attr && path->attr->ipv6_ecommunity) { + if (path && path->attr && bgp_attr_get_ipv6_ecommunity(path->attr)) { struct ecommunity_val_ipv6 *ipv6_ecom_eval; - ecom = path->attr->ipv6_ecommunity; + ecom = bgp_attr_get_ipv6_ecommunity(path->attr); for (i = 0; i < ecom->size; i++) { ipv6_ecom_eval = (struct ecommunity_val_ipv6 *) (ecom->val + (i * ecom->unit_size)); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index f8a29821d8..8d87f2cd04 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -241,6 +241,9 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra) if (e->bgp_orig) bgp_unlock(e->bgp_orig); + if (e->aggr_suppressors) + list_delete(&e->aggr_suppressors); + if ((*extra)->bgp_fs_iprule) list_delete(&((*extra)->bgp_fs_iprule)); if ((*extra)->bgp_fs_pbr) @@ -1439,14 +1442,15 @@ static bool bgp_community_filter(struct peer *peer, struct attr *attr) static bool bgp_cluster_filter(struct peer *peer, struct attr *attr) { struct in_addr cluster_id; + struct cluster_list *cluster = bgp_attr_get_cluster(attr); - if (attr->cluster) { + if (cluster) { if (peer->bgp->config & BGP_CONFIG_CLUSTER_ID) cluster_id = peer->bgp->cluster_id; else cluster_id = peer->bgp->router_id; - if (cluster_loop_check(attr->cluster, cluster_id)) + if (cluster_loop_check(cluster, cluster_id)) return true; } return false; @@ -1500,7 +1504,7 @@ static int bgp_input_modifier(struct peer *peer, const struct prefix *p, SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN); /* Apply BGP route map to the attribute. */ - ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path); + ret = route_map_apply(rmap, p, &rmap_path); peer->rmap_type = 0; @@ -1551,7 +1555,7 @@ static int bgp_output_modifier(struct peer *peer, const struct prefix *p, SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT); /* Apply BGP route map to the attribute. */ - ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path); + ret = route_map_apply(rmap, p, &rmap_path); peer->rmap_type = rmap_type; @@ -2047,10 +2051,10 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, if (bgp_path_suppressed(pi)) ret = route_map_apply(UNSUPPRESS_MAP(filter), p, - RMAP_BGP, &rmap_path); + &rmap_path); else ret = route_map_apply(ROUTE_MAP_OUT(filter), p, - RMAP_BGP, &rmap_path); + &rmap_path); peer->rmap_type = 0; @@ -2497,10 +2501,13 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp, struct attr attr; afi_t afi; safi_t safi; + struct bgp *bgp; + bool advertise; p = bgp_dest_get_prefix(dest); afi = SUBGRP_AFI(subgrp); safi = SUBGRP_SAFI(subgrp); + bgp = SUBGRP_INST(subgrp); onlypeer = ((SUBGRP_PCOUNT(subgrp) == 1) ? (SUBGRP_PFIRST(subgrp))->peer : NULL); @@ -2515,13 +2522,23 @@ void subgroup_process_announce_selected(struct update_subgroup *subgrp, memset(&attr, 0, sizeof(struct attr)); /* It's initialized in bgp_announce_check() */ - /* Announcement to the subgroup. If the route is filtered withdraw it. + /* Announcement to the subgroup. If the route is filtered withdraw it. + * If BGP_NODE_FIB_INSTALL_PENDING is set and data plane install status + * is pending (BGP_NODE_FIB_INSTALL_PENDING), do not advertise the + * route */ + advertise = bgp_check_advertise(bgp, dest); + if (selected) { if (subgroup_announce_check(dest, selected, subgrp, p, &attr, - false)) - bgp_adj_out_set_subgroup(dest, subgrp, &attr, selected); - else + false)) { + /* Route is selected, if the route is already installed + * in FIB, then it is advertised + */ + if (advertise) + bgp_adj_out_set_subgroup(dest, subgrp, &attr, + selected); + } else bgp_adj_out_unset_subgroup(dest, subgrp, 1, addpath_tx_id); } @@ -2620,7 +2637,7 @@ static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi, RESET_FLAG(dummy_attr.rmap_change_flags); ret = route_map_apply(bgp->adv_cmd_rmap[afi][safi].map, - p, RMAP_BGP, &rmap_path); + p, &rmap_path); if (ret == RMAP_DENYMATCH) { bgp_attr_flush(&dummy_attr); @@ -3370,17 +3387,22 @@ static void overlay_index_update(struct attr *attr, if (!attr) return; if (gw_ip == NULL) { - memset(&(attr->evpn_overlay.gw_ip), 0, sizeof(union gw_addr)); + struct bgp_route_evpn eo; + + memset(&eo, 0, sizeof(eo)); + bgp_attr_set_evpn_overlay(attr, &eo); } else { - memcpy(&(attr->evpn_overlay.gw_ip), gw_ip, - sizeof(union gw_addr)); + struct bgp_route_evpn eo = {.gw_ip = *gw_ip}; + + bgp_attr_set_evpn_overlay(attr, &eo); } } static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path, union gw_addr *gw_ip) { - union gw_addr *path_gw_ip, *path_gw_ip_remote; + const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(path->attr); + union gw_addr path_gw_ip, *path_gw_ip_remote; union { esi_t esi; union gw_addr ip; @@ -3389,7 +3411,7 @@ static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path, if (afi != AFI_L2VPN) return true; - path_gw_ip = &(path->attr->evpn_overlay.gw_ip); + path_gw_ip = eo->gw_ip; if (gw_ip == NULL) { memset(&temp, 0, sizeof(temp)); @@ -3397,7 +3419,7 @@ static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path, } else path_gw_ip_remote = gw_ip; - return !!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr)); + return !!memcmp(&path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr)); } /* Check if received nexthop is valid or not. */ @@ -3525,6 +3547,22 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, else has_valid_label = bgp_is_valid_label(label); + if (has_valid_label) + assert(label != NULL); + + /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following + * condition : + * Suppress fib is enabled + * BGP_OPT_NO_FIB is not enabled + * Route type is BGP_ROUTE_NORMAL (peer learnt routes) + * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set) + */ + if (BGP_SUPPRESS_FIB_ENABLED(bgp) && + (sub_type == BGP_ROUTE_NORMAL) && + (!bgp_option_check(BGP_OPT_NO_FIB)) && + (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED))) + SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING); + /* When peer's soft reconfiguration enabled. Record input packet in Adj-RIBs-In. */ if (!soft_reconfig @@ -4480,7 +4518,8 @@ static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi, if (num_labels) label_pnt = &pi->extra->label[0]; if (pi) - memcpy(&evpn, &pi->attr->evpn_overlay, + memcpy(&evpn, + bgp_attr_get_evpn_overlay(pi->attr), sizeof(evpn)); else memset(&evpn, 0, sizeof(evpn)); @@ -5189,8 +5228,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p, SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK); - ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP, - &rmap_path); + ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path); bgp->peer_self->rmap_type = 0; @@ -5509,8 +5547,7 @@ static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p, SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK); - ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP, - &rmap_path); + ret = route_map_apply(bgp_static->rmap.map, p, &rmap_path); bgp->peer_self->rmap_type = 0; @@ -6361,7 +6398,7 @@ static bool aggr_suppress_map_test(struct bgp *bgp, rmap_path.attr = &attr; SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_AGGREGATE); - rmr = route_map_apply(aggregate->suppress_map, p, RMAP_BGP, &rmap_path); + rmr = route_map_apply(aggregate->suppress_map, p, &rmap_path); bgp->peer_self->rmap_type = 0; bgp_attr_flush(&attr); @@ -6789,6 +6826,12 @@ void bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi, if (dest_p->prefixlen <= p->prefixlen) continue; + /* If suppress fib is enabled and route not installed + * in FIB, skip the route + */ + if (!bgp_check_advertise(bgp, dest)) + continue; + match = 0; for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { @@ -7284,6 +7327,12 @@ void bgp_aggregate_increment(struct bgp *bgp, const struct prefix *p, if (BGP_PATH_HOLDDOWN(pi)) return; + /* If suppress fib is enabled and route not installed + * in FIB, do not update the aggregate route + */ + if (!bgp_check_advertise(bgp, pi->net)) + return; + child = bgp_node_get(table, p); /* Aggregate address configuration check. */ @@ -7807,8 +7856,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE); - ret = route_map_apply(red->rmap.map, p, RMAP_BGP, - &rmap_path); + ret = route_map_apply(red->rmap.map, p, &rmap_path); bgp->peer_self->rmap_type = 0; @@ -8926,13 +8974,12 @@ void route_vty_out_overlay(struct vty *vty, const struct prefix *p, } } - if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) { - inet_ntop(AF_INET, &(attr->evpn_overlay.gw_ip.ipv4), buf, - BUFSIZ); - } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) { - inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6), buf, - BUFSIZ); - } + const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr); + + if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) + inet_ntop(AF_INET, &eo->gw_ip.ipv4, buf, BUFSIZ); + else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) + inet_ntop(AF_INET6, &eo->gw_ip.ipv6, buf, BUFSIZ); if (!json_path) vty_out(vty, "/%s", buf); @@ -10018,6 +10065,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, } if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)) { + struct cluster_list *cluster = + bgp_attr_get_cluster(attr); int i; if (json_paths) { @@ -10025,13 +10074,11 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, json_cluster_list_list = json_object_new_array(); - for (i = 0; i < attr->cluster->length / 4; - i++) { + for (i = 0; i < cluster->length / 4; i++) { json_string = json_object_new_string( - inet_ntop( - AF_INET, - &attr->cluster->list[i], - buf, sizeof(buf))); + inet_ntop(AF_INET, + &cluster->list[i], + buf, sizeof(buf))); json_object_array_add( json_cluster_list_list, json_string); @@ -10043,7 +10090,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, * do. Add this someday if someone asks * for it. * json_object_string_add(json_cluster_list, - * "string", attr->cluster->str); + * "string", cluster->str); */ json_object_object_add(json_cluster_list, "list", @@ -10053,10 +10100,9 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, } else { vty_out(vty, ", Cluster list: "); - for (i = 0; i < attr->cluster->length / 4; - i++) { + for (i = 0; i < cluster->length / 4; i++) { vty_out(vty, "%pI4 ", - &attr->cluster->list[i]); + &cluster->list[i]); } } } @@ -10183,9 +10229,9 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, /* Line 10 display PMSI tunnel attribute, if present */ if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PMSI_TUNNEL)) { - const char *str = - lookup_msg(bgp_pmsi_tnltype_str, attr->pmsi_tnl_type, - PMSI_TNLTYPE_STR_DEFAULT); + const char *str = lookup_msg(bgp_pmsi_tnltype_str, + bgp_attr_get_pmsi_tnl_type(attr), + PMSI_TNLTYPE_STR_DEFAULT); if (json_paths) { json_pmsi = json_object_new_object(); @@ -10354,8 +10400,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, path.peer = pi->peer; path.attr = &dummy_attr; - ret = route_map_apply(rmap, dest_p, RMAP_BGP, - &path); + ret = route_map_apply(rmap, dest_p, &path); if (ret == RMAP_DENYMATCH) continue; } @@ -11168,6 +11213,7 @@ static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc, char *str; int first = 0; uint8_t show_flags = 0; + int ret; if (uj) SET_FLAG(show_flags, BGP_SHOW_OPT_JSON); @@ -11195,10 +11241,13 @@ static int bgp_show_lcommunity(struct vty *vty, struct bgp *bgp, int argc, return CMD_WARNING; } - return bgp_show(vty, bgp, afi, safi, + ret = bgp_show(vty, bgp, afi, safi, (exact ? bgp_show_type_lcommunity_exact : bgp_show_type_lcommunity), lcom, show_flags); + + lcommunity_free(&lcom); + return ret; } static int bgp_show_lcommunity_list(struct vty *vty, struct bgp *bgp, diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index e4c6f9a0e2..0b76d7504b 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -524,6 +524,13 @@ static inline void prep_for_rmap_apply(struct bgp_path_info *dst_pi, } } +static inline bool bgp_check_advertise(struct bgp *bgp, struct bgp_dest *dest) +{ + return (!(BGP_SUPPRESS_FIB_ENABLED(bgp) && + CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING) && + (!bgp_option_check(BGP_OPT_NO_FIB)))); +} + /* called before bgp_process() */ DECLARE_HOOK(bgp_process, (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn, diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index e4a9c29000..637eaca397 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -244,8 +244,7 @@ struct bgp_match_peer_compiled { received in bgp_path_info->peer. If it is the same, or if the peer structure received is a peer_group containing it, returns RMAP_MATCH. */ static enum route_map_cmd_result_t -route_match_peer(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_peer(void *rule, const struct prefix *prefix, void *object) { struct bgp_match_peer_compiled *pc; union sockunion *su; @@ -255,56 +254,51 @@ route_match_peer(void *rule, const struct prefix *prefix, struct peer *peer; struct listnode *node, *nnode; - if (type == RMAP_BGP) { - pc = rule; - su = &pc->su; - peer = ((struct bgp_path_info *)object)->peer; + pc = rule; + su = &pc->su; + peer = ((struct bgp_path_info *)object)->peer; - if (pc->interface) { - if (!peer->conf_if) - return RMAP_NOMATCH; + if (pc->interface) { + if (!peer->conf_if) + return RMAP_NOMATCH; - if (strcmp(peer->conf_if, pc->interface) == 0) - return RMAP_MATCH; + if (strcmp(peer->conf_if, pc->interface) == 0) + return RMAP_MATCH; - return RMAP_NOMATCH; - } + return RMAP_NOMATCH; + } - /* If su='0.0.0.0' (command 'match peer local'), and it's a - NETWORK, - REDISTRIBUTE, AGGREGATE-ADDRESS or DEFAULT_GENERATED route - => return RMAP_MATCH - */ - if (sockunion_same(su, &su_def)) { - int ret; - if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_NETWORK) - || CHECK_FLAG(peer->rmap_type, - PEER_RMAP_TYPE_REDISTRIBUTE) - || CHECK_FLAG(peer->rmap_type, - PEER_RMAP_TYPE_AGGREGATE) - || CHECK_FLAG(peer->rmap_type, - PEER_RMAP_TYPE_DEFAULT)) - ret = RMAP_MATCH; - else - ret = RMAP_NOMATCH; - return ret; - } + /* If su='0.0.0.0' (command 'match peer local'), and it's a + NETWORK, + REDISTRIBUTE, AGGREGATE-ADDRESS or DEFAULT_GENERATED route + => return RMAP_MATCH + */ + if (sockunion_same(su, &su_def)) { + int ret; + if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_NETWORK) + || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE) + || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_AGGREGATE) + || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_DEFAULT)) + ret = RMAP_MATCH; + else + ret = RMAP_NOMATCH; + return ret; + } + + if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + if (sockunion_same(su, &peer->su)) + return RMAP_MATCH; - if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + return RMAP_NOMATCH; + } else { + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) { if (sockunion_same(su, &peer->su)) return RMAP_MATCH; - - return RMAP_NOMATCH; - } else { - group = peer->group; - for (ALL_LIST_ELEMENTS(group->peer, node, nnode, - peer)) { - if (sockunion_same(su, &peer->su)) - return RMAP_MATCH; - } - return RMAP_NOMATCH; } + return RMAP_NOMATCH; } + return RMAP_NOMATCH; } @@ -345,8 +339,7 @@ static const struct route_map_rule_cmd route_match_peer_cmd = { #if defined(HAVE_LUA) static enum route_map_cmd_result_t -route_match_command(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_command(void *rule, const struct prefix *prefix, void *object) { int status = RMAP_NOMATCH; u_int32_t locpref = 0; @@ -443,12 +436,11 @@ static const struct route_map_rule_cmd route_match_command_cmd = { /* Match function should return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_ip_address(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_address(void *rule, const struct prefix *prefix, void *object) { struct access_list *alist; - if (type == RMAP_BGP && prefix->family == AF_INET) { + if (prefix->family == AF_INET) { alist = access_list_lookup(AFI_IP, (char *)rule); if (alist == NULL) return RMAP_NOMATCH; @@ -485,14 +477,13 @@ static const struct route_map_rule_cmd route_match_ip_address_cmd = { /* Match function return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_ip_next_hop(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_next_hop(void *rule, const struct prefix *prefix, void *object) { struct access_list *alist; struct bgp_path_info *path; struct prefix_ipv4 p; - if (type == RMAP_BGP && prefix->family == AF_INET) { + if (prefix->family == AF_INET) { path = object; p.family = AF_INET; p.prefix = path->attr->nexthop; @@ -534,15 +525,14 @@ static const struct route_map_rule_cmd route_match_ip_next_hop_cmd = { /* Match function return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_ip_route_source(void *rule, const struct prefix *pfx, - route_map_object_t type, void *object) +route_match_ip_route_source(void *rule, const struct prefix *pfx, void *object) { struct access_list *alist; struct bgp_path_info *path; struct peer *peer; struct prefix_ipv4 p; - if (type == RMAP_BGP && pfx->family == AF_INET) { + if (pfx->family == AF_INET) { path = object; peer = path->peer; @@ -624,14 +614,10 @@ route_match_prefix_list_flowspec(afi_t afi, struct prefix_list *plist, static enum route_map_cmd_result_t route_match_address_prefix_list(void *rule, afi_t afi, - const struct prefix *prefix, - route_map_object_t type, void *object) + const struct prefix *prefix, void *object) { struct prefix_list *plist; - if (type != RMAP_BGP) - return RMAP_NOMATCH; - plist = prefix_list_lookup(afi, (char *)rule); if (plist == NULL) return RMAP_NOMATCH; @@ -645,10 +631,9 @@ route_match_address_prefix_list(void *rule, afi_t afi, static enum route_map_cmd_result_t route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { - return route_match_address_prefix_list(rule, AFI_IP, prefix, type, - object); + return route_match_address_prefix_list(rule, AFI_IP, prefix, object); } static void *route_match_ip_address_prefix_list_compile(const char *arg) @@ -673,13 +658,13 @@ static const struct route_map_rule_cmd static enum route_map_cmd_result_t route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { struct prefix_list *plist; struct bgp_path_info *path; struct prefix_ipv4 p; - if (type == RMAP_BGP && prefix->family == AF_INET) { + if (prefix->family == AF_INET) { path = object; p.family = AF_INET; p.prefix = path->attr->nexthop; @@ -718,11 +703,11 @@ static const struct route_map_rule_cmd static enum route_map_cmd_result_t route_match_ip_next_hop_type(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { struct bgp_path_info *path; - if (type == RMAP_BGP && prefix->family == AF_INET) { + if (prefix->family == AF_INET) { path = (struct bgp_path_info *)object; if (!path) return RMAP_NOMATCH; @@ -759,16 +744,15 @@ static const struct route_map_rule_cmd /* `match ip route-source prefix-list PREFIX_LIST' */ static enum route_map_cmd_result_t -route_match_ip_route_source_prefix_list(void *rule, - const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_route_source_prefix_list(void *rule, const struct prefix *prefix, + void *object) { struct prefix_list *plist; struct bgp_path_info *path; struct peer *peer; struct prefix_ipv4 p; - if (type == RMAP_BGP && prefix->family == AF_INET) { + if (prefix->family == AF_INET) { path = object; peer = path->peer; @@ -812,10 +796,9 @@ static const struct route_map_rule_cmd /* Match function should return 1 if match is success else 0 */ static enum route_map_cmd_result_t -route_match_evpn_default_route(void *rule, const struct prefix *p, - route_map_object_t type, void *object) +route_match_evpn_default_route(void *rule, const struct prefix *p, void *object) { - if (type == RMAP_BGP && is_evpn_prefix_default(p)) + if (is_evpn_prefix_default(p)) return RMAP_MATCH; return RMAP_NOMATCH; @@ -835,30 +818,24 @@ static const struct route_map_rule_cmd /* Match function should return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_mac_address(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_mac_address(void *rule, const struct prefix *prefix, void *object) { struct access_list *alist; struct prefix p; - if (type == RMAP_BGP) { - alist = access_list_lookup(AFI_L2VPN, (char *)rule); - if (alist == NULL) - return RMAP_NOMATCH; - - if (prefix->u.prefix_evpn.route_type != BGP_EVPN_MAC_IP_ROUTE) - return RMAP_NOMATCH; + alist = access_list_lookup(AFI_L2VPN, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; - p.family = AF_ETHERNET; - p.prefixlen = ETH_ALEN * 8; - p.u.prefix_eth = prefix->u.prefix_evpn.macip_addr.mac; + if (prefix->u.prefix_evpn.route_type != BGP_EVPN_MAC_IP_ROUTE) + return RMAP_NOMATCH; - return (access_list_apply(alist, &p) == FILTER_DENY - ? RMAP_NOMATCH - : RMAP_MATCH); - } + p.family = AF_ETHERNET; + p.prefixlen = ETH_ALEN * 8; + p.u.prefix_eth = prefix->u.prefix_evpn.macip_addr.mac; - return RMAP_NOMATCH; + return (access_list_apply(alist, &p) == FILTER_DENY ? RMAP_NOMATCH + : RMAP_MATCH); } /* Route map `mac address' match statement. `arg' should be @@ -889,43 +866,42 @@ static const struct route_map_rule_cmd route_match_mac_address_cmd = { * ...RMAP_NOOP to ignore this match check. */ static enum route_map_cmd_result_t -route_match_vni(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_vni(void *rule, const struct prefix *prefix, void *object) { vni_t vni = 0; unsigned int label_cnt = 0; struct bgp_path_info *path = NULL; struct prefix_evpn *evp = (struct prefix_evpn *) prefix; - if (type == RMAP_BGP) { - vni = *((vni_t *)rule); - path = (struct bgp_path_info *)object; + vni = *((vni_t *)rule); + path = (struct bgp_path_info *)object; - /* - * This rmap filter is valid for vxlan tunnel type only. - * For any other tunnel type, return noop to ignore - * this check. - */ - if (path->attr->encap_tunneltype != BGP_ENCAP_TYPE_VXLAN) - return RMAP_NOOP; + /* + * This rmap filter is valid for vxlan tunnel type only. + * For any other tunnel type, return noop to ignore + * this check. + */ + if (path->attr->encap_tunneltype != BGP_ENCAP_TYPE_VXLAN) + return RMAP_NOOP; - /* - * Apply filter to type 1, 2, 5 routes only. - * Other route types do not have vni label. - */ - if (evp && (evp->prefix.route_type != BGP_EVPN_AD_ROUTE && - evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE && - evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE)) - return RMAP_NOOP; + /* + * Apply filter to type 1, 2, 5 routes only. + * Other route types do not have vni label. + */ + if (evp + && (evp->prefix.route_type != BGP_EVPN_AD_ROUTE + && evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE + && evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE)) + return RMAP_NOOP; - if (path->extra == NULL) - return RMAP_NOMATCH; + if (path->extra == NULL) + return RMAP_NOMATCH; - for ( ; label_cnt < BGP_MAX_LABELS && - label_cnt < path->extra->num_labels; label_cnt++) { - if (vni == label2vni(&path->extra->label[label_cnt])) - return RMAP_MATCH; - } + for (; + label_cnt < BGP_MAX_LABELS && label_cnt < path->extra->num_labels; + label_cnt++) { + if (vni == label2vni(&path->extra->label[label_cnt])) + return RMAP_MATCH; } return RMAP_NOMATCH; @@ -967,17 +943,14 @@ static const struct route_map_rule_cmd route_match_evpn_vni_cmd = { /* Match function should return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_evpn_route_type(void *rule, const struct prefix *pfx, - route_map_object_t type, void *object) +route_match_evpn_route_type(void *rule, const struct prefix *pfx, void *object) { uint8_t route_type = 0; - if (type == RMAP_BGP) { - route_type = *((uint8_t *)rule); + route_type = *((uint8_t *)rule); - if (route_type == pfx->u.prefix_evpn.route_type) - return RMAP_MATCH; - } + if (route_type == pfx->u.prefix_evpn.route_type) + return RMAP_MATCH; return RMAP_NOMATCH; } @@ -1017,28 +990,24 @@ static const struct route_map_rule_cmd route_match_evpn_route_type_cmd = { /* Match function should return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_rd(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_rd(void *rule, const struct prefix *prefix, void *object) { struct prefix_rd *prd_rule = NULL; const struct prefix_rd *prd_route = NULL; struct bgp_path_info *path = NULL; - if (type == RMAP_BGP) { - if (prefix->family != AF_EVPN) - return RMAP_NOMATCH; + if (prefix->family != AF_EVPN) + return RMAP_NOMATCH; - prd_rule = (struct prefix_rd *)rule; - path = (struct bgp_path_info *)object; + prd_rule = (struct prefix_rd *)rule; + path = (struct bgp_path_info *)object; - if (path->net == NULL || path->net->pdest == NULL) - return RMAP_NOMATCH; + if (path->net == NULL || path->net->pdest == NULL) + return RMAP_NOMATCH; - prd_route = (struct prefix_rd *)bgp_dest_get_prefix( - path->net->pdest); - if (memcmp(prd_route->val, prd_rule->val, ECOMMUNITY_SIZE) == 0) - return RMAP_MATCH; - } + prd_route = (struct prefix_rd *)bgp_dest_get_prefix(path->net->pdest); + if (memcmp(prd_route->val, prd_rule->val, ECOMMUNITY_SIZE) == 0) + return RMAP_MATCH; return RMAP_NOMATCH; } @@ -1077,26 +1046,24 @@ static const struct route_map_rule_cmd route_match_evpn_rd_cmd = { /* Route map commands for VRF route leak with source vrf matching */ static enum route_map_cmd_result_t route_match_vrl_source_vrf(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { struct bgp_path_info *path; char *vrf_name; - if (type == RMAP_BGP) { - vrf_name = rule; - path = (struct bgp_path_info *)object; + vrf_name = rule; + path = (struct bgp_path_info *)object; - if (strncmp(vrf_name, "n/a", VRF_NAMSIZ) == 0) - return RMAP_NOMATCH; + if (strncmp(vrf_name, "n/a", VRF_NAMSIZ) == 0) + return RMAP_NOMATCH; - if (path->extra == NULL) - return RMAP_NOMATCH; + if (path->extra == NULL) + return RMAP_NOMATCH; - if (strncmp(vrf_name, vrf_id_to_name( - path->extra->bgp_orig->vrf_id), VRF_NAMSIZ) - == 0) - return RMAP_MATCH; - } + if (strncmp(vrf_name, vrf_id_to_name(path->extra->bgp_orig->vrf_id), + VRF_NAMSIZ) + == 0) + return RMAP_MATCH; return RMAP_NOMATCH; } @@ -1127,22 +1094,18 @@ static const struct route_map_rule_cmd route_match_vrl_source_vrf_cmd = { /* Match function return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_local_pref(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_local_pref(void *rule, const struct prefix *prefix, void *object) { uint32_t *local_pref; struct bgp_path_info *path; - if (type == RMAP_BGP) { - local_pref = rule; - path = object; + local_pref = rule; + path = object; - if (path->attr->local_pref == *local_pref) - return RMAP_MATCH; - else - return RMAP_NOMATCH; - } - return RMAP_NOMATCH; + if (path->attr->local_pref == *local_pref) + return RMAP_MATCH; + else + return RMAP_NOMATCH; } /* @@ -1188,18 +1151,14 @@ static const struct route_map_rule_cmd route_match_local_pref_cmd = { /* Match function return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_metric(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_metric(void *rule, const struct prefix *prefix, void *object) { struct rmap_value *rv; struct bgp_path_info *path; - if (type == RMAP_BGP) { - rv = rule; - path = object; - return route_value_match(rv, path->attr->med); - } - return RMAP_NOMATCH; + rv = rule; + path = object; + return route_value_match(rv, path->attr->med); } /* Route map commands for metric matching. */ @@ -1214,27 +1173,22 @@ static const struct route_map_rule_cmd route_match_metric_cmd = { /* Match function for as-path match. I assume given object is */ static enum route_map_cmd_result_t -route_match_aspath(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_aspath(void *rule, const struct prefix *prefix, void *object) { struct as_list *as_list; struct bgp_path_info *path; - if (type == RMAP_BGP) { - as_list = as_list_lookup((char *)rule); - if (as_list == NULL) - return RMAP_NOMATCH; + as_list = as_list_lookup((char *)rule); + if (as_list == NULL) + return RMAP_NOMATCH; - path = object; + path = object; - /* Perform match. */ - return ((as_list_apply(as_list, path->attr->aspath) - == AS_FILTER_DENY) - ? RMAP_NOMATCH - : RMAP_MATCH); - } - return RMAP_NOMATCH; + /* Perform match. */ + return ((as_list_apply(as_list, path->attr->aspath) == AS_FILTER_DENY) + ? RMAP_NOMATCH + : RMAP_MATCH); } /* Compile function for as-path match. */ @@ -1266,32 +1220,28 @@ struct rmap_community { /* Match function for community match. */ static enum route_map_cmd_result_t -route_match_community(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_community(void *rule, const struct prefix *prefix, void *object) { struct community_list *list; struct bgp_path_info *path; struct rmap_community *rcom = rule; - if (type == RMAP_BGP) { - path = object; - rcom = rule; + path = object; + rcom = rule; - list = community_list_lookup(bgp_clist, rcom->name, - rcom->name_hash, - COMMUNITY_LIST_MASTER); - if (!list) - return RMAP_NOMATCH; + list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash, + COMMUNITY_LIST_MASTER); + if (!list) + return RMAP_NOMATCH; - if (rcom->exact) { - if (community_list_exact_match(path->attr->community, - list)) - return RMAP_MATCH; - } else { - if (community_list_match(path->attr->community, list)) - return RMAP_MATCH; - } + if (rcom->exact) { + if (community_list_exact_match(path->attr->community, list)) + return RMAP_MATCH; + } else { + if (community_list_match(path->attr->community, list)) + return RMAP_MATCH; } + return RMAP_NOMATCH; } @@ -1355,34 +1305,27 @@ static const struct route_map_rule_cmd route_match_community_cmd = { /* Match function for lcommunity match. */ static enum route_map_cmd_result_t -route_match_lcommunity(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_lcommunity(void *rule, const struct prefix *prefix, void *object) { struct community_list *list; struct bgp_path_info *path; struct rmap_community *rcom = rule; - if (type == RMAP_BGP) { - path = object; + path = object; - list = community_list_lookup(bgp_clist, rcom->name, - rcom->name_hash, - LARGE_COMMUNITY_LIST_MASTER); - if (!list) - return RMAP_NOMATCH; + list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash, + LARGE_COMMUNITY_LIST_MASTER); + if (!list) + return RMAP_NOMATCH; - if (rcom->exact) { - if (lcommunity_list_exact_match( - path->attr->lcommunity, - list)) - return RMAP_MATCH; - } else { - if (lcommunity_list_match( - path->attr->lcommunity, - list)) - return RMAP_MATCH; - } + if (rcom->exact) { + if (lcommunity_list_exact_match(path->attr->lcommunity, list)) + return RMAP_MATCH; + } else { + if (lcommunity_list_match(path->attr->lcommunity, list)) + return RMAP_MATCH; } + return RMAP_NOMATCH; } @@ -1431,25 +1374,22 @@ static const struct route_map_rule_cmd route_match_lcommunity_cmd = { /* Match function for extcommunity match. */ static enum route_map_cmd_result_t -route_match_ecommunity(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ecommunity(void *rule, const struct prefix *prefix, void *object) { struct community_list *list; struct bgp_path_info *path; struct rmap_community *rcom = rule; - if (type == RMAP_BGP) { - path = object; + path = object; - list = community_list_lookup(bgp_clist, rcom->name, - rcom->name_hash, - EXTCOMMUNITY_LIST_MASTER); - if (!list) - return RMAP_NOMATCH; + list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash, + EXTCOMMUNITY_LIST_MASTER); + if (!list) + return RMAP_NOMATCH; + + if (ecommunity_list_match(path->attr->ecommunity, list)) + return RMAP_MATCH; - if (ecommunity_list_match(path->attr->ecommunity, list)) - return RMAP_MATCH; - } return RMAP_NOMATCH; } @@ -1487,19 +1427,16 @@ static const struct route_map_rule_cmd route_match_ecommunity_cmd = { /* `match origin' */ static enum route_map_cmd_result_t -route_match_origin(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_origin(void *rule, const struct prefix *prefix, void *object) { uint8_t *origin; struct bgp_path_info *path; - if (type == RMAP_BGP) { - origin = rule; - path = object; + origin = rule; + path = object; - if (path->attr->origin == *origin) - return RMAP_MATCH; - } + if (path->attr->origin == *origin) + return RMAP_MATCH; return RMAP_NOMATCH; } @@ -1537,8 +1474,7 @@ static const struct route_map_rule_cmd route_match_origin_cmd = { /* match probability { */ static enum route_map_cmd_result_t -route_match_probability(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_probability(void *rule, const struct prefix *prefix, void *object) { long r = frr_weak_random(); @@ -1594,26 +1530,22 @@ static const struct route_map_rule_cmd route_match_probability_cmd = { /* Match function should return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_interface(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_interface(void *rule, const struct prefix *prefix, void *object) { struct interface *ifp; struct bgp_path_info *path; - if (type == RMAP_BGP) { - path = object; + path = object; - if (!path) - return RMAP_NOMATCH; + if (!path) + return RMAP_NOMATCH; - ifp = if_lookup_by_name_all_vrf((char *)rule); + ifp = if_lookup_by_name_all_vrf((char *)rule); - if (ifp == NULL || ifp->ifindex != path->attr->nh_ifindex) - return RMAP_NOMATCH; + if (ifp == NULL || ifp->ifindex != path->attr->nh_ifindex) + return RMAP_NOMATCH; - return RMAP_MATCH; - } - return RMAP_NOMATCH; + return RMAP_MATCH; } /* Route map `interface' match statement. `arg' should be @@ -1643,20 +1575,15 @@ static const struct route_map_rule_cmd route_match_interface_cmd = { /* Match function return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_tag(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_tag(void *rule, const struct prefix *prefix, void *object) { route_tag_t *tag; struct bgp_path_info *path; - if (type == RMAP_BGP) { - tag = rule; - path = object; - - return ((path->attr->tag == *tag) ? RMAP_MATCH : RMAP_NOMATCH); - } + tag = rule; + path = object; - return RMAP_NOMATCH; + return ((path->attr->tag == *tag) ? RMAP_MATCH : RMAP_NOMATCH); } @@ -1669,15 +1596,11 @@ static const struct route_map_rule_cmd route_match_tag_cmd = { }; static enum route_map_cmd_result_t -route_set_srte_color(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_srte_color(void *rule, const struct prefix *prefix, void *object) { uint32_t *srte_color = rule; struct bgp_path_info *path; - if (type != RMAP_BGP) - return RMAP_OKAY; - path = object; path->attr->srte_color = *srte_color; @@ -1716,16 +1639,12 @@ struct rmap_ip_nexthop_set { }; static enum route_map_cmd_result_t -route_set_ip_nexthop(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_ip_nexthop(void *rule, const struct prefix *prefix, void *object) { struct rmap_ip_nexthop_set *rins = rule; struct bgp_path_info *path; struct peer *peer; - if (type != RMAP_BGP) - return RMAP_OKAY; - if (prefix->family == AF_INET6) return RMAP_OKAY; @@ -1824,26 +1743,22 @@ static const struct route_map_rule_cmd route_set_ip_nexthop_cmd = { /* Set local preference. */ static enum route_map_cmd_result_t -route_set_local_pref(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_local_pref(void *rule, const struct prefix *prefix, void *object) { struct rmap_value *rv; struct bgp_path_info *path; uint32_t locpref = 0; - if (type == RMAP_BGP) { - /* Fetch routemap's rule information. */ - rv = rule; - path = object; + /* Fetch routemap's rule information. */ + rv = rule; + path = object; - /* Set local preference value. */ - if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) - locpref = path->attr->local_pref; + /* Set local preference value. */ + if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) + locpref = path->attr->local_pref; - path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF); - path->attr->local_pref = - route_value_adjust(rv, locpref, path->peer); - } + path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF); + path->attr->local_pref = route_value_adjust(rv, locpref, path->peer); return RMAP_OKAY; } @@ -1860,20 +1775,17 @@ static const struct route_map_rule_cmd route_set_local_pref_cmd = { /* Set weight. */ static enum route_map_cmd_result_t -route_set_weight(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_weight(void *rule, const struct prefix *prefix, void *object) { struct rmap_value *rv; struct bgp_path_info *path; - if (type == RMAP_BGP) { - /* Fetch routemap's rule information. */ - rv = rule; - path = object; + /* Fetch routemap's rule information. */ + rv = rule; + path = object; - /* Set weight value. */ - path->attr->weight = route_value_adjust(rv, 0, path->peer); - } + /* Set weight value. */ + path->attr->weight = route_value_adjust(rv, 0, path->peer); return RMAP_OKAY; } @@ -1888,15 +1800,11 @@ static const struct route_map_rule_cmd route_set_weight_cmd = { /* `set distance DISTANCE */ static enum route_map_cmd_result_t -route_set_distance(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_distance(void *rule, const struct prefix *prefix, void *object) { struct bgp_path_info *path = object; struct rmap_value *rv = rule; - if (type != RMAP_BGP) - return RMAP_OKAY; - path->attr->distance = rv->value; return RMAP_OKAY; @@ -1914,24 +1822,22 @@ static const struct route_map_rule_cmd route_set_distance_cmd = { /* Set metric to attribute. */ static enum route_map_cmd_result_t -route_set_metric(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_metric(void *rule, const struct prefix *prefix, void *object) { struct rmap_value *rv; struct bgp_path_info *path; uint32_t med = 0; - if (type == RMAP_BGP) { - /* Fetch routemap's rule information. */ - rv = rule; - path = object; + /* Fetch routemap's rule information. */ + rv = rule; + path = object; - if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) - med = path->attr->med; + if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) + med = path->attr->med; + + path->attr->med = route_value_adjust(rv, med, path->peer); + path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); - path->attr->med = route_value_adjust(rv, med, path->peer); - path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); - } return RMAP_OKAY; } @@ -1945,21 +1851,20 @@ static const struct route_map_rule_cmd route_set_metric_cmd = { /* `set table (1-4294967295)' */ -static enum route_map_cmd_result_t route_set_table_id(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_table_id(void *rule, const struct prefix *prefix, + + void *object) { struct rmap_value *rv; struct bgp_path_info *path; - if (type == RMAP_BGP) { - /* Fetch routemap's rule information. */ - rv = rule; - path = object; + /* Fetch routemap's rule information. */ + rv = rule; + path = object; + + path->attr->rmap_table_id = rv->value; - path->attr->rmap_table_id = rv->value; - } return RMAP_OKAY; } @@ -1975,34 +1880,31 @@ static const struct route_map_rule_cmd route_set_table_id_cmd = { /* For AS path prepend mechanism. */ static enum route_map_cmd_result_t -route_set_aspath_prepend(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_aspath_prepend(void *rule, const struct prefix *prefix, void *object) { struct aspath *aspath; struct aspath *new; struct bgp_path_info *path; - if (type == RMAP_BGP) { - path = object; - - if (path->attr->aspath->refcnt) - new = aspath_dup(path->attr->aspath); - else - new = path->attr->aspath; + path = object; - if ((uintptr_t)rule > 10) { - aspath = rule; - aspath_prepend(aspath, new); - } else { - as_t as = aspath_leftmost(new); - if (!as) - as = path->peer->as; - new = aspath_add_seq_n(new, as, (uintptr_t)rule); - } + if (path->attr->aspath->refcnt) + new = aspath_dup(path->attr->aspath); + else + new = path->attr->aspath; - path->attr->aspath = new; + if ((uintptr_t)rule > 10) { + aspath = rule; + aspath_prepend(aspath, new); + } else { + as_t as = aspath_leftmost(new); + if (!as) + as = path->peer->as; + new = aspath_add_seq_n(new, as, (uintptr_t)rule); } + path->attr->aspath = new; + return RMAP_OKAY; } @@ -2039,22 +1941,19 @@ static const struct route_map_rule_cmd route_set_aspath_prepend_cmd = { * Make a deep copy of existing AS_PATH, but for the first ASn only. */ static enum route_map_cmd_result_t -route_set_aspath_exclude(void *rule, const struct prefix *dummy, - route_map_object_t type, void *object) +route_set_aspath_exclude(void *rule, const struct prefix *dummy, void *object) { struct aspath *new_path, *exclude_path; struct bgp_path_info *path; - if (type == RMAP_BGP) { - exclude_path = rule; - path = object; - if (path->attr->aspath->refcnt) - new_path = aspath_dup(path->attr->aspath); - else - new_path = path->attr->aspath; - path->attr->aspath = - aspath_filter_exclude(new_path, exclude_path); - } + exclude_path = rule; + path = object; + if (path->attr->aspath->refcnt) + new_path = aspath_dup(path->attr->aspath); + else + new_path = path->attr->aspath; + path->attr->aspath = aspath_filter_exclude(new_path, exclude_path); + return RMAP_OKAY; } @@ -2075,8 +1974,7 @@ struct rmap_com_set { /* For community set mechanism. */ static enum route_map_cmd_result_t -route_set_community(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_community(void *rule, const struct prefix *prefix, void *object) { struct rmap_com_set *rcs; struct bgp_path_info *path; @@ -2085,44 +1983,42 @@ route_set_community(void *rule, const struct prefix *prefix, struct community *old; struct community *merge; - if (type == RMAP_BGP) { - rcs = rule; - path = object; - attr = path->attr; - old = attr->community; - - /* "none" case. */ - if (rcs->none) { - attr->flag &= ~(ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)); - attr->community = NULL; - /* See the longer comment down below. */ - if (old && old->refcnt == 0) - community_free(&old); - return RMAP_OKAY; - } + rcs = rule; + path = object; + attr = path->attr; + old = attr->community; + + /* "none" case. */ + if (rcs->none) { + attr->flag &= ~(ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)); + attr->community = NULL; + /* See the longer comment down below. */ + if (old && old->refcnt == 0) + community_free(&old); + return RMAP_OKAY; + } - /* "additive" case. */ - if (rcs->additive && old) { - merge = community_merge(community_dup(old), rcs->com); + /* "additive" case. */ + if (rcs->additive && old) { + merge = community_merge(community_dup(old), rcs->com); - new = community_uniq_sort(merge); - community_free(&merge); - } else - new = community_dup(rcs->com); + new = community_uniq_sort(merge); + community_free(&merge); + } else + new = community_dup(rcs->com); - /* HACK: if the old community is not intern'd, - * we should free it here, or all reference to it may be - * lost. - * Really need to cleanup attribute caching sometime. - */ - if (old && old->refcnt == 0) - community_free(&old); + /* HACK: if the old community is not intern'd, + * we should free it here, or all reference to it may be + * lost. + * Really need to cleanup attribute caching sometime. + */ + if (old && old->refcnt == 0) + community_free(&old); - /* will be interned by caller if required */ - attr->community = new; + /* will be interned by caller if required */ + attr->community = new; - attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES); - } + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES); return RMAP_OKAY; } @@ -2192,8 +2088,7 @@ struct rmap_lcom_set { /* For lcommunity set mechanism. */ static enum route_map_cmd_result_t -route_set_lcommunity(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_lcommunity(void *rule, const struct prefix *prefix, void *object) { struct rmap_lcom_set *rcs; struct bgp_path_info *path; @@ -2202,46 +2097,42 @@ route_set_lcommunity(void *rule, const struct prefix *prefix, struct lcommunity *old; struct lcommunity *merge; - if (type == RMAP_BGP) { - rcs = rule; - path = object; - attr = path->attr; - old = attr->lcommunity; - - /* "none" case. */ - if (rcs->none) { - attr->flag &= - ~(ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)); - attr->lcommunity = NULL; - - /* See the longer comment down below. */ - if (old && old->refcnt == 0) - lcommunity_free(&old); - return RMAP_OKAY; - } - - if (rcs->additive && old) { - merge = lcommunity_merge(lcommunity_dup(old), - rcs->lcom); + rcs = rule; + path = object; + attr = path->attr; + old = attr->lcommunity; - new = lcommunity_uniq_sort(merge); - lcommunity_free(&merge); - } else - new = lcommunity_dup(rcs->lcom); + /* "none" case. */ + if (rcs->none) { + attr->flag &= ~(ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)); + attr->lcommunity = NULL; - /* HACK: if the old large-community is not intern'd, - * we should free it here, or all reference to it may be - * lost. - * Really need to cleanup attribute caching sometime. - */ + /* See the longer comment down below. */ if (old && old->refcnt == 0) lcommunity_free(&old); + return RMAP_OKAY; + } - /* will be intern()'d or attr_flush()'d by bgp_update_main() */ - attr->lcommunity = new; + if (rcs->additive && old) { + merge = lcommunity_merge(lcommunity_dup(old), rcs->lcom); - attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES); - } + new = lcommunity_uniq_sort(merge); + lcommunity_free(&merge); + } else + new = lcommunity_dup(rcs->lcom); + + /* HACK: if the old large-community is not intern'd, + * we should free it here, or all reference to it may be + * lost. + * Really need to cleanup attribute caching sometime. + */ + if (old && old->refcnt == 0) + lcommunity_free(&old); + + /* will be intern()'d or attr_flush()'d by bgp_update_main() */ + attr->lcommunity = new; + + attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES); return RMAP_OKAY; } @@ -2306,8 +2197,7 @@ static const struct route_map_rule_cmd route_set_lcommunity_cmd = { /* For large community set mechanism. */ static enum route_map_cmd_result_t -route_set_lcommunity_delete(void *rule, const struct prefix *pfx, - route_map_object_t type, void *object) +route_set_lcommunity_delete(void *rule, const struct prefix *pfx, void *object) { struct community_list *list; struct lcommunity *merge; @@ -2316,40 +2206,36 @@ route_set_lcommunity_delete(void *rule, const struct prefix *pfx, struct bgp_path_info *path; struct rmap_community *rcom = rule; - if (type == RMAP_BGP) { - if (!rcom) - return RMAP_OKAY; + if (!rcom) + return RMAP_OKAY; - path = object; - list = community_list_lookup(bgp_clist, rcom->name, - rcom->name_hash, - LARGE_COMMUNITY_LIST_MASTER); - old = path->attr->lcommunity; - - if (list && old) { - merge = lcommunity_list_match_delete( - lcommunity_dup(old), list); - new = lcommunity_uniq_sort(merge); - lcommunity_free(&merge); - - /* HACK: if the old community is not intern'd, - * we should free it here, or all reference to it may be - * lost. - * Really need to cleanup attribute caching sometime. - */ - if (old->refcnt == 0) - lcommunity_free(&old); - - if (new->size == 0) { - path->attr->lcommunity = NULL; - path->attr->flag &= ~ATTR_FLAG_BIT( - BGP_ATTR_LARGE_COMMUNITIES); - lcommunity_free(&new); - } else { - path->attr->lcommunity = new; - path->attr->flag |= ATTR_FLAG_BIT( - BGP_ATTR_LARGE_COMMUNITIES); - } + path = object; + list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash, + LARGE_COMMUNITY_LIST_MASTER); + old = path->attr->lcommunity; + + if (list && old) { + merge = lcommunity_list_match_delete(lcommunity_dup(old), list); + new = lcommunity_uniq_sort(merge); + lcommunity_free(&merge); + + /* HACK: if the old community is not intern'd, + * we should free it here, or all reference to it may be + * lost. + * Really need to cleanup attribute caching sometime. + */ + if (old->refcnt == 0) + lcommunity_free(&old); + + if (new->size == 0) { + path->attr->lcommunity = NULL; + path->attr->flag &= + ~ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES); + lcommunity_free(&new); + } else { + path->attr->lcommunity = new; + path->attr->flag |= + ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES); } } @@ -2399,7 +2285,7 @@ static const struct route_map_rule_cmd route_set_lcommunity_delete_cmd = { /* For community set mechanism. */ static enum route_map_cmd_result_t route_set_community_delete(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { struct community_list *list; struct community *merge; @@ -2408,40 +2294,35 @@ route_set_community_delete(void *rule, const struct prefix *prefix, struct bgp_path_info *path; struct rmap_community *rcom = rule; - if (type == RMAP_BGP) { - if (!rcom) - return RMAP_OKAY; + if (!rcom) + return RMAP_OKAY; - path = object; - list = community_list_lookup(bgp_clist, rcom->name, - rcom->name_hash, - COMMUNITY_LIST_MASTER); - old = path->attr->community; - - if (list && old) { - merge = community_list_match_delete(community_dup(old), - list); - new = community_uniq_sort(merge); - community_free(&merge); - - /* HACK: if the old community is not intern'd, - * we should free it here, or all reference to it may be - * lost. - * Really need to cleanup attribute caching sometime. - */ - if (old->refcnt == 0) - community_free(&old); - - if (new->size == 0) { - path->attr->community = NULL; - path->attr->flag &= - ~ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES); - community_free(&new); - } else { - path->attr->community = new; - path->attr->flag |= - ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES); - } + path = object; + list = community_list_lookup(bgp_clist, rcom->name, rcom->name_hash, + COMMUNITY_LIST_MASTER); + old = path->attr->community; + + if (list && old) { + merge = community_list_match_delete(community_dup(old), list); + new = community_uniq_sort(merge); + community_free(&merge); + + /* HACK: if the old community is not intern'd, + * we should free it here, or all reference to it may be + * lost. + * Really need to cleanup attribute caching sometime. + */ + if (old->refcnt == 0) + community_free(&old); + + if (new->size == 0) { + path->attr->community = NULL; + path->attr->flag &= + ~ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES); + community_free(&new); + } else { + path->attr->community = new; + path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES); } } @@ -2489,42 +2370,39 @@ static const struct route_map_rule_cmd route_set_community_delete_cmd = { /* For community set mechanism. Used by _rt and _soo. */ static enum route_map_cmd_result_t -route_set_ecommunity(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_ecommunity(void *rule, const struct prefix *prefix, void *object) { struct ecommunity *ecom; struct ecommunity *new_ecom; struct ecommunity *old_ecom; struct bgp_path_info *path; - if (type == RMAP_BGP) { - ecom = rule; - path = object; + ecom = rule; + path = object; - if (!ecom) - return RMAP_OKAY; + if (!ecom) + return RMAP_OKAY; - /* We assume additive for Extended Community. */ - old_ecom = path->attr->ecommunity; + /* We assume additive for Extended Community. */ + old_ecom = path->attr->ecommunity; - if (old_ecom) { - new_ecom = ecommunity_merge(ecommunity_dup(old_ecom), - ecom); + if (old_ecom) { + new_ecom = ecommunity_merge(ecommunity_dup(old_ecom), ecom); - /* old_ecom->refcnt = 1 => owned elsewhere, e.g. - * bgp_update_receive() - * ->refcnt = 0 => set by a previous route-map - * statement */ - if (!old_ecom->refcnt) - ecommunity_free(&old_ecom); - } else - new_ecom = ecommunity_dup(ecom); + /* old_ecom->refcnt = 1 => owned elsewhere, e.g. + * bgp_update_receive() + * ->refcnt = 0 => set by a previous route-map + * statement */ + if (!old_ecom->refcnt) + ecommunity_free(&old_ecom); + } else + new_ecom = ecommunity_dup(ecom); - /* will be intern()'d or attr_flush()'d by bgp_update_main() */ - path->attr->ecommunity = new_ecom; + /* will be intern()'d or attr_flush()'d by bgp_update_main() */ + path->attr->ecommunity = new_ecom; + + path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES); - path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES); - } return RMAP_OKAY; } @@ -2588,8 +2466,7 @@ struct rmap_ecomm_lb_set { }; static enum route_map_cmd_result_t -route_set_ecommunity_lb(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object) { struct rmap_ecomm_lb_set *rels = rule; struct bgp_path_info *path; @@ -2602,9 +2479,6 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, struct ecommunity *old_ecom; as_t as; - if (type != RMAP_BGP) - return RMAP_OKAY; - path = object; peer = path->peer; if (!peer || !peer->bgp) @@ -2721,18 +2595,15 @@ struct route_map_rule_cmd route_set_ecommunity_lb_cmd = { /* For origin set. */ static enum route_map_cmd_result_t -route_set_origin(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_origin(void *rule, const struct prefix *prefix, void *object) { uint8_t *origin; struct bgp_path_info *path; - if (type == RMAP_BGP) { - origin = rule; - path = object; + origin = rule; + path = object; - path->attr->origin = *origin; - } + path->attr->origin = *origin; return RMAP_OKAY; } @@ -2772,15 +2643,12 @@ static const struct route_map_rule_cmd route_set_origin_cmd = { /* For atomic aggregate set. */ static enum route_map_cmd_result_t -route_set_atomic_aggregate(void *rule, const struct prefix *pfx, - route_map_object_t type, void *object) +route_set_atomic_aggregate(void *rule, const struct prefix *pfx, void *object) { struct bgp_path_info *path; - if (type == RMAP_BGP) { - path = object; - path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE); - } + path = object; + path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE); return RMAP_OKAY; } @@ -2812,20 +2680,17 @@ struct aggregator { }; static enum route_map_cmd_result_t -route_set_aggregator_as(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_aggregator_as(void *rule, const struct prefix *prefix, void *object) { struct bgp_path_info *path; struct aggregator *aggregator; - if (type == RMAP_BGP) { - path = object; - aggregator = rule; + path = object; + aggregator = rule; - path->attr->aggregator_as = aggregator->as; - path->attr->aggregator_addr = aggregator->address; - path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR); - } + path->attr->aggregator_as = aggregator->as; + path->attr->aggregator_addr = aggregator->address; + path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR); return RMAP_OKAY; } @@ -2867,19 +2732,16 @@ static const struct route_map_rule_cmd route_set_aggregator_as_cmd = { /* Set tag to object. object must be pointer to struct bgp_path_info */ static enum route_map_cmd_result_t -route_set_tag(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_tag(void *rule, const struct prefix *prefix, void *object) { route_tag_t *tag; struct bgp_path_info *path; - if (type == RMAP_BGP) { - tag = rule; - path = object; + tag = rule; + path = object; - /* Set tag value */ - path->attr->tag = *tag; - } + /* Set tag value */ + path->attr->tag = *tag; return RMAP_OKAY; } @@ -2894,24 +2756,21 @@ static const struct route_map_rule_cmd route_set_tag_cmd = { /* Set label-index to object. object must be pointer to struct bgp_path_info */ static enum route_map_cmd_result_t -route_set_label_index(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_label_index(void *rule, const struct prefix *prefix, void *object) { struct rmap_value *rv; struct bgp_path_info *path; uint32_t label_index; - if (type == RMAP_BGP) { - /* Fetch routemap's rule information. */ - rv = rule; - path = object; + /* Fetch routemap's rule information. */ + rv = rule; + path = object; - /* Set label-index value. */ - label_index = rv->value; - if (label_index) { - path->attr->label_index = label_index; - path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID); - } + /* Set label-index value. */ + label_index = rv->value; + if (label_index) { + path->attr->label_index = label_index; + path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID); } return RMAP_OKAY; @@ -2928,12 +2787,11 @@ static const struct route_map_rule_cmd route_set_label_index_cmd = { /* `match ipv6 address IP_ACCESS_LIST' */ static enum route_map_cmd_result_t -route_match_ipv6_address(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object) { struct access_list *alist; - if (type == RMAP_BGP && prefix->family == AF_INET6) { + if (prefix->family == AF_INET6) { alist = access_list_lookup(AFI_IP6, (char *)rule); if (alist == NULL) return RMAP_NOMATCH; @@ -2966,25 +2824,19 @@ static const struct route_map_rule_cmd route_match_ipv6_address_cmd = { /* `match ipv6 next-hop IP_ADDRESS' */ static enum route_map_cmd_result_t -route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ipv6_next_hop(void *rule, const struct prefix *prefix, void *object) { struct in6_addr *addr = rule; struct bgp_path_info *path; - if (type == RMAP_BGP) { - path = object; - - if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr)) - return RMAP_MATCH; + path = object; - if (path->attr->mp_nexthop_len - == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL - && IPV6_ADDR_SAME(&path->attr->mp_nexthop_local, rule)) - return RMAP_MATCH; + if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr)) + return RMAP_MATCH; - return RMAP_NOMATCH; - } + if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL + && IPV6_ADDR_SAME(&path->attr->mp_nexthop_local, rule)) + return RMAP_MATCH; return RMAP_NOMATCH; } @@ -3020,22 +2872,17 @@ static const struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = { /* `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) +route_match_ipv4_next_hop(void *rule, const struct prefix *prefix, 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; + path = object; - return RMAP_NOMATCH; - } + 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; } @@ -3072,10 +2919,9 @@ static const struct route_map_rule_cmd route_match_ipv4_next_hop_cmd = { static enum route_map_cmd_result_t route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { - return route_match_address_prefix_list(rule, AFI_IP6, prefix, type, - object); + return route_match_address_prefix_list(rule, AFI_IP6, prefix, object); } static void *route_match_ipv6_address_prefix_list_compile(const char *arg) @@ -3100,12 +2946,12 @@ static const struct route_map_rule_cmd static enum route_map_cmd_result_t route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { struct bgp_path_info *path; struct in6_addr *addr = rule; - if (type == RMAP_BGP && prefix->family == AF_INET6) { + if (prefix->family == AF_INET6) { path = (struct bgp_path_info *)object; if (!path) return RMAP_NOMATCH; @@ -3114,6 +2960,7 @@ route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix, && !path->attr->nh_ifindex) return RMAP_MATCH; } + return RMAP_NOMATCH; } @@ -3150,27 +2997,24 @@ static const struct route_map_rule_cmd /* Set nexthop to object. ojbect must be pointer to struct attr. */ static enum route_map_cmd_result_t -route_set_ipv6_nexthop_global(void *rule, const struct prefix *p, - route_map_object_t type, void *object) +route_set_ipv6_nexthop_global(void *rule, const struct prefix *p, void *object) { struct in6_addr *address; struct bgp_path_info *path; - if (type == RMAP_BGP) { - /* Fetch routemap's rule information. */ - address = rule; - path = object; + /* Fetch routemap's rule information. */ + address = rule; + path = object; - /* Set next hop value. */ - path->attr->mp_nexthop_global = *address; + /* Set next hop value. */ + path->attr->mp_nexthop_global = *address; - /* Set nexthop length. */ - if (path->attr->mp_nexthop_len == 0) - path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; + /* Set nexthop length. */ + if (path->attr->mp_nexthop_len == 0) + path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; - SET_FLAG(path->attr->rmap_change_flags, - BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED); - } + SET_FLAG(path->attr->rmap_change_flags, + BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED); return RMAP_OKAY; } @@ -3212,28 +3056,27 @@ static const struct route_map_rule_cmd /* Set next-hop preference value. */ static enum route_map_cmd_result_t route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { struct bgp_path_info *path; struct peer *peer; - if (type == RMAP_BGP) { - /* Fetch routemap's rule information. */ - path = object; - peer = path->peer; + /* Fetch routemap's rule information. */ + path = object; + peer = path->peer; - if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN) - || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) { - /* Set next hop preference to global */ - path->attr->mp_nexthop_prefer_global = true; - SET_FLAG(path->attr->rmap_change_flags, - BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED); - } else { - path->attr->mp_nexthop_prefer_global = false; - SET_FLAG(path->attr->rmap_change_flags, - BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED); - } + if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN) + || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) { + /* Set next hop preference to global */ + path->attr->mp_nexthop_prefer_global = true; + SET_FLAG(path->attr->rmap_change_flags, + BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED); + } else { + path->attr->mp_nexthop_prefer_global = false; + SET_FLAG(path->attr->rmap_change_flags, + BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED); } + return RMAP_OKAY; } @@ -3266,29 +3109,24 @@ static const struct route_map_rule_cmd /* Set nexthop to object. ojbect must be pointer to struct attr. */ static enum route_map_cmd_result_t -route_set_ipv6_nexthop_local(void *rule, const struct prefix *p, - route_map_object_t type, void *object) +route_set_ipv6_nexthop_local(void *rule, const struct prefix *p, void *object) { struct in6_addr *address; struct bgp_path_info *path; - if (type == RMAP_BGP) { - /* Fetch routemap's rule information. */ - address = rule; - path = object; + /* Fetch routemap's rule information. */ + address = rule; + path = object; - /* Set next hop value. */ - path->attr->mp_nexthop_local = *address; + /* Set next hop value. */ + path->attr->mp_nexthop_local = *address; - /* Set nexthop length. */ - if (path->attr->mp_nexthop_len - != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) - path->attr->mp_nexthop_len = - BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; + /* Set nexthop length. */ + if (path->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) + path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; - SET_FLAG(path->attr->rmap_change_flags, - BATTR_RMAP_IPV6_LL_NHOP_CHANGED); - } + SET_FLAG(path->attr->rmap_change_flags, + BATTR_RMAP_IPV6_LL_NHOP_CHANGED); return RMAP_OKAY; } @@ -3331,55 +3169,52 @@ static const struct route_map_rule_cmd /* Set nexthop to object. ojbect must be pointer to struct attr. */ static enum route_map_cmd_result_t -route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx, - route_map_object_t type, void *object) +route_set_ipv6_nexthop_peer(void *rule, const struct prefix *pfx, void *object) { struct in6_addr peer_address; struct bgp_path_info *path; struct peer *peer; - if (type == RMAP_BGP) { - /* Fetch routemap's rule information. */ - path = object; - peer = path->peer; - - if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN) - || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) - && peer->su_remote - && sockunion_family(peer->su_remote) == AF_INET6) { - peer_address = peer->su_remote->sin6.sin6_addr; - /* Set next hop value and length in attribute. */ - if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) { - path->attr->mp_nexthop_local = peer_address; - if (path->attr->mp_nexthop_len - != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) - path->attr->mp_nexthop_len = - BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; - } else { - path->attr->mp_nexthop_global = peer_address; - if (path->attr->mp_nexthop_len == 0) - path->attr->mp_nexthop_len = - BGP_ATTR_NHLEN_IPV6_GLOBAL; - } + /* Fetch routemap's rule information. */ + path = object; + peer = path->peer; - } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) { - /* The next hop value will be set as part of packet - * rewrite. - * Set the flags here to indicate that rewrite needs to - * be done. - * Also, clear the value - we clear both global and - * link-local - * nexthops, whether we send one or both is determined - * elsewhere. - */ - SET_FLAG(path->attr->rmap_change_flags, - BATTR_RMAP_NEXTHOP_PEER_ADDRESS); - /* clear next hop value. */ - memset(&(path->attr->mp_nexthop_global), 0, - sizeof(struct in6_addr)); - memset(&(path->attr->mp_nexthop_local), 0, - sizeof(struct in6_addr)); + if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN) + || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) + && peer->su_remote + && sockunion_family(peer->su_remote) == AF_INET6) { + peer_address = peer->su_remote->sin6.sin6_addr; + /* Set next hop value and length in attribute. */ + if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) { + path->attr->mp_nexthop_local = peer_address; + if (path->attr->mp_nexthop_len + != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) + path->attr->mp_nexthop_len = + BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; + } else { + path->attr->mp_nexthop_global = peer_address; + if (path->attr->mp_nexthop_len == 0) + path->attr->mp_nexthop_len = + BGP_ATTR_NHLEN_IPV6_GLOBAL; } + + } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) { + /* The next hop value will be set as part of packet + * rewrite. + * Set the flags here to indicate that rewrite needs to + * be done. + * Also, clear the value - we clear both global and + * link-local + * nexthops, whether we send one or both is determined + * elsewhere. + */ + SET_FLAG(path->attr->rmap_change_flags, + BATTR_RMAP_NEXTHOP_PEER_ADDRESS); + /* clear next hop value. */ + memset(&(path->attr->mp_nexthop_global), 0, + sizeof(struct in6_addr)); + memset(&(path->attr->mp_nexthop_local), 0, + sizeof(struct in6_addr)); } return RMAP_OKAY; @@ -3414,21 +3249,18 @@ static const struct route_map_rule_cmd route_set_ipv6_nexthop_peer_cmd = { /* `set ipv4 vpn next-hop A.B.C.D' */ static enum route_map_cmd_result_t -route_set_vpnv4_nexthop(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_vpnv4_nexthop(void *rule, const struct prefix *prefix, void *object) { struct in_addr *address; struct bgp_path_info *path; - if (type == RMAP_BGP) { - /* Fetch routemap's rule information. */ - address = rule; - path = object; + /* Fetch routemap's rule information. */ + address = rule; + path = object; - /* Set next hop value. */ - path->attr->mp_nexthop_global_in = *address; - path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; - } + /* Set next hop value. */ + path->attr->mp_nexthop_global_in = *address; + path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV4; return RMAP_OKAY; } @@ -3453,22 +3285,19 @@ static void *route_set_vpnv4_nexthop_compile(const char *arg) /* `set ipv6 vpn next-hop A.B.C.D' */ static enum route_map_cmd_result_t -route_set_vpnv6_nexthop(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_vpnv6_nexthop(void *rule, const struct prefix *prefix, void *object) { struct in6_addr *address; struct bgp_path_info *path; - if (type == RMAP_BGP) { - /* Fetch routemap's rule information. */ - address = rule; - path = object; + /* Fetch routemap's rule information. */ + address = rule; + path = object; - /* Set next hop value. */ - memcpy(&path->attr->mp_nexthop_global, address, - sizeof(struct in6_addr)); - path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL; - } + /* Set next hop value. */ + memcpy(&path->attr->mp_nexthop_global, address, + sizeof(struct in6_addr)); + path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL; return RMAP_OKAY; } @@ -3514,19 +3343,16 @@ static const struct route_map_rule_cmd route_set_vpnv6_nexthop_cmd = { /* For origin set. */ static enum route_map_cmd_result_t -route_set_originator_id(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_originator_id(void *rule, const struct prefix *prefix, void *object) { struct in_addr *address; struct bgp_path_info *path; - if (type == RMAP_BGP) { - address = rule; - path = object; + address = rule; + path = object; - path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID); - path->attr->originator_id = *address; - } + path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID); + path->attr->originator_id = *address; return RMAP_OKAY; } diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c index 0f0aff7eaa..24ee99bddb 100644 --- a/bgpd/bgp_rpki.c +++ b/bgpd/bgp_rpki.c @@ -124,7 +124,7 @@ static int is_running(void); static void route_match_free(void *rule); static enum route_map_cmd_result_t route_match(void *rule, const struct prefix *prefix, - route_map_object_t type, + void *object); static void *route_match_compile(const char *arg); static void revalidate_bgp_node(struct bgp_dest *dest, afi_t afi, safi_t safi); @@ -213,20 +213,18 @@ static void ipv6_addr_to_host_byte_order(const uint32_t *src, uint32_t *dest) static enum route_map_cmd_result_t route_match(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) { int *rpki_status = rule; struct bgp_path_info *path; - if (type == RMAP_BGP) { - path = object; + path = object; - if (rpki_validate_prefix(path->peer, path->attr, prefix) - == *rpki_status) { - return RMAP_MATCH; - } + if (rpki_validate_prefix(path->peer, path->attr, prefix) + == *rpki_status) { + return RMAP_MATCH; } + return RMAP_NOMATCH; } diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h index 4e9abf863d..738d41ee6d 100644 --- a/bgpd/bgp_table.h +++ b/bgpd/bgp_table.h @@ -102,6 +102,8 @@ struct bgp_node { #define BGP_NODE_LABEL_CHANGED (1 << 2) #define BGP_NODE_REGISTERED_FOR_LABEL (1 << 3) #define BGP_NODE_SELECT_DEFER (1 << 4) +#define BGP_NODE_FIB_INSTALL_PENDING (1 << 5) +#define BGP_NODE_FIB_INSTALLED (1 << 6) struct bgp_addpath_node_data tx_addpath; diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index 3cfb73d8a8..da9e1f28ae 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -315,6 +315,7 @@ static void updgrp_show_adj(struct bgp *bgp, afi_t afi, safi_t safi, static int subgroup_coalesce_timer(struct thread *thread) { struct update_subgroup *subgrp; + struct bgp *bgp; subgrp = THREAD_ARG(thread); if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0)) @@ -323,6 +324,7 @@ static int subgroup_coalesce_timer(struct thread *thread) subgrp->v_coalesce); subgrp->t_coalesce = NULL; subgrp->v_coalesce = 0; + bgp = SUBGRP_INST(subgrp); subgroup_announce_route(subgrp); @@ -334,7 +336,8 @@ static int subgroup_coalesce_timer(struct thread *thread) * to * announce, this is the method currently employed to trigger the EOR. */ - if (!bgp_update_delay_active(SUBGRP_INST(subgrp))) { + if (!bgp_update_delay_active(SUBGRP_INST(subgrp)) && + !(BGP_SUPPRESS_FIB_ENABLED(bgp))) { struct peer_af *paf; struct peer *peer; @@ -458,10 +461,14 @@ void bgp_adj_out_set_subgroup(struct bgp_dest *dest, struct peer *peer; afi_t afi; safi_t safi; + struct peer *adv_peer; + struct peer_af *paf; + struct bgp *bgp; peer = SUBGRP_PEER(subgrp); afi = SUBGRP_AFI(subgrp); safi = SUBGRP_SAFI(subgrp); + bgp = SUBGRP_INST(subgrp); if (DISABLE_BGP_ANNOUNCE) return; @@ -504,9 +511,21 @@ void bgp_adj_out_set_subgroup(struct bgp_dest *dest, * mrai timers so the socket writes can happen. */ if (!bgp_adv_fifo_count(&subgrp->sync->update)) { - struct peer_af *paf; - SUBGRP_FOREACH_PEER (subgrp, paf) { + /* If there are no routes in the withdraw list, set + * the flag PEER_STATUS_ADV_DELAY which will allow + * more routes to be sent in the update message + */ + if (BGP_SUPPRESS_FIB_ENABLED(bgp)) { + adv_peer = PAF_PEER(paf); + if (!bgp_adv_fifo_count( + &subgrp->sync->withdraw)) + SET_FLAG(adv_peer->thread_flags, + PEER_THREAD_SUBGRP_ADV_DELAY); + else + UNSET_FLAG(adv_peer->thread_flags, + PEER_THREAD_SUBGRP_ADV_DELAY); + } bgp_adjust_routeadv(PAF_PEER(paf)); } } @@ -617,10 +636,13 @@ void subgroup_announce_table(struct update_subgroup *subgrp, afi_t afi; safi_t safi; int addpath_capable; + struct bgp *bgp; + bool advertise; peer = SUBGRP_PEER(subgrp); afi = SUBGRP_AFI(subgrp); safi = SUBGRP_SAFI(subgrp); + bgp = SUBGRP_INST(subgrp); addpath_capable = bgp_addpath_encode_tx(peer, afi, safi); if (safi == SAFI_LABELED_UNICAST) @@ -637,6 +659,9 @@ void subgroup_announce_table(struct update_subgroup *subgrp, for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) { const struct prefix *dest_p = bgp_dest_get_prefix(dest); + /* Check if the route can be advertised */ + advertise = bgp_check_advertise(bgp, dest); + for (ri = bgp_dest_get_bgp_path_info(dest); ri; ri = ri->next) if (CHECK_FLAG(ri->flags, BGP_PATH_SELECTED) @@ -646,10 +671,14 @@ void subgroup_announce_table(struct update_subgroup *subgrp, ri))) { if (subgroup_announce_check(dest, ri, subgrp, dest_p, &attr, - false)) - bgp_adj_out_set_subgroup(dest, subgrp, - &attr, ri); - else { + false)) { + /* Check if route can be advertised */ + if (advertise) + bgp_adj_out_set_subgroup(dest, + subgrp, + &attr, + ri); + } else { /* If default originate is enabled for * the peer, do not send explicit * withdraw. This will prevent deletion @@ -794,8 +823,7 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) ret = route_map_apply( peer->default_rmap[afi][safi].map, - bgp_dest_get_prefix(dest), RMAP_BGP, - &tmp_pi); + bgp_dest_get_prefix(dest), &tmp_pi); if (ret == RMAP_DENYMATCH) { bgp_attr_flush(&tmp_attr); @@ -813,8 +841,10 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) break; } } - if (ret == RMAP_PERMITMATCH) + if (ret == RMAP_PERMITMATCH) { + bgp_dest_unlock_node(dest); break; + } } bgp->peer_self->rmap_type = 0; @@ -944,6 +974,13 @@ void group_announce_route(struct bgp *bgp, afi_t afi, safi_t safi, struct updwalk_context ctx; ctx.pi = pi; ctx.dest = dest; + + /* If suppress fib is enabled, the route will be advertised when + * FIB status is received + */ + if (!bgp_check_advertise(bgp, dest)) + return; + update_group_af_walk(bgp, afi, safi, group_announce_route_walkcb, &ctx); } diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 6977223b83..40e9707866 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -1514,6 +1514,20 @@ void cli_show_router_bgp_router_id(struct vty *vty, struct lyd_node *dnode, vty_out(vty, " bgp router-id %s\n", yang_dnode_get_string(dnode, NULL)); } +DEFPY (bgp_suppress_fib_pending, + bgp_suppress_fib_pending_cmd, + "[no] bgp suppress-fib-pending", + NO_STR + BGP_STR + "Advertise only routes that are programmed in kernel to peers\n") +{ + VTY_DECLVAR_CONTEXT(bgp, bgp); + + bgp_suppress_fib_pending_set(bgp, !no); + return CMD_SUCCESS; +} + + /* BGP Cluster ID. */ DEFUN_YANG(bgp_cluster_id, bgp_cluster_id_cmd, @@ -16833,6 +16847,10 @@ int bgp_config_write(struct vty *vty) vty_out(vty, " bgp router-id %pI4\n", &bgp->router_id_static); + /* Suppress fib pending */ + if (CHECK_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_FIB_PENDING)) + vty_out(vty, " bgp suppress-fib-pending\n"); + /* BGP log-neighbor-changes. */ if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_LOG_NEIGHBOR_CHANGES) != SAVE_BGP_LOG_NEIGHBOR_CHANGES) @@ -17348,6 +17366,9 @@ void bgp_vty_init(void) install_element(BGP_NODE, &bgp_router_id_cmd); install_element(BGP_NODE, &no_bgp_router_id_cmd); + /* "bgp suppress-fib-pending" command */ + install_element(BGP_NODE, &bgp_suppress_fib_pending_cmd); + /* "bgp cluster-id" commands. */ install_element(BGP_NODE, &bgp_cluster_id_cmd); install_element(BGP_NODE, &no_bgp_cluster_id_cmd); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 957db4cbc1..73f03f6a9d 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -531,9 +531,9 @@ static int zebra_read_route(ZAPI_CALLBACK_ARGS) api.instance, &api.prefix, buf, nhtype, ifindex, api.metric, api.tag); } else { - zlog_debug("Rx route DEL VRF %u %s[%d] %s", vrf_id, + zlog_debug("Rx route DEL VRF %u %s[%d] %pFX", vrf_id, zebra_route_string(api.type), api.instance, - buf); + &api.prefix); } } @@ -918,7 +918,7 @@ static bool bgp_table_map_apply(struct route_map *map, const struct prefix *p, { route_map_result_t ret; - ret = route_map_apply(map, p, RMAP_BGP, path); + ret = route_map_apply(map, p, path); bgp_attr_flush(path->attr); if (ret != RMAP_DENYMATCH) @@ -2380,6 +2380,99 @@ static int iptable_notify_owner(ZAPI_CALLBACK_ARGS) return 0; } +/* Process route notification messages from RIB */ +static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) +{ + struct prefix p; + enum zapi_route_notify_owner note; + uint32_t table_id; + char buf[PREFIX_STRLEN]; + afi_t afi; + safi_t safi; + struct bgp_dest *dest; + struct bgp *bgp; + struct bgp_path_info *pi, *new_select; + + if (!zapi_route_notify_decode(zclient->ibuf, &p, &table_id, ¬e, + &afi, &safi)) { + zlog_err("%s : error in msg decode", __PRETTY_FUNCTION__); + return -1; + } + + /* Get the bgp instance */ + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) { + flog_err(EC_BGP_INVALID_BGP_INSTANCE, + "%s : bgp instance not found vrf %d", + __PRETTY_FUNCTION__, vrf_id); + return -1; + } + + if (BGP_DEBUG(zebra, ZEBRA)) + prefix2str(&p, buf, sizeof(buf)); + + /* Find the bgp route node */ + dest = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi, &p, + &bgp->vrf_prd); + if (!dest) + return -1; + + bgp_dest_unlock_node(dest); + + switch (note) { + case ZAPI_ROUTE_INSTALLED: + new_select = NULL; + /* Clear the flags so that route can be processed */ + if (CHECK_FLAG(dest->flags, + BGP_NODE_FIB_INSTALL_PENDING)) { + UNSET_FLAG(dest->flags, + BGP_NODE_FIB_INSTALL_PENDING); + SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED); + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("route %s : INSTALLED", buf); + /* Find the best route */ + for (pi = dest->info; pi; pi = pi->next) { + /* Process aggregate route */ + bgp_aggregate_increment(bgp, &p, pi, + afi, safi); + if (CHECK_FLAG(pi->flags, + BGP_PATH_SELECTED)) + new_select = pi; + } + /* Advertise the route */ + if (new_select) + group_announce_route(bgp, afi, safi, + dest, new_select); + else { + flog_err(EC_BGP_INVALID_ROUTE, + "selected route %s not found", + buf); + return -1; + } + } + break; + case ZAPI_ROUTE_REMOVED: + /* Route deleted from dataplane, reset the installed flag + * so that route can be reinstalled when client sends + * route add later + */ + UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED); + break; + case ZAPI_ROUTE_FAIL_INSTALL: + /* Error will be logged by zebra module */ + break; + case ZAPI_ROUTE_BETTER_ADMIN_WON: + /* No action required */ + break; + case ZAPI_ROUTE_REMOVE_FAIL: + zlog_warn("%s: Route %s failure to remove", + __func__, buf); + break; + } + return 0; +} + /* this function is used to forge ip rule, * - either for iptable/ipset using fwmark id * - or for sample ip rule cmd @@ -2747,6 +2840,7 @@ static int bgp_zebra_process_local_macip(ZAPI_CALLBACK_ARGS) stream_get(&esi, s, sizeof(esi_t)); } else { state = stream_getl(s); + memset(&esi, 0, sizeof(esi_t)); } bgp = bgp_lookup_by_vrf_id(vrf_id); @@ -2910,6 +3004,7 @@ void bgp_zebra_init(struct thread_master *master, unsigned short instance) zclient->ipset_notify_owner = ipset_notify_owner; zclient->ipset_entry_notify_owner = ipset_entry_notify_owner; zclient->iptable_notify_owner = iptable_notify_owner; + zclient->route_notify_owner = bgp_zebra_route_notify_owner; zclient->instance = instance; } diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index df453dd993..b773c16b57 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -109,6 +109,9 @@ struct community_list_handler *bgp_clist; unsigned int multipath_num = MULTIPATH_NUM; +/* Number of bgp instances configured for suppress fib config */ +unsigned int bgp_suppress_fib_count; + static void bgp_if_finish(struct bgp *bgp); static void peer_drop_dynamic_neighbor(struct peer *peer); @@ -390,6 +393,43 @@ void bgp_router_id_static_set(struct bgp *bgp, struct in_addr id) true /* is config */); } +/* Set the suppress fib pending for the bgp configuration */ +void bgp_suppress_fib_pending_set(struct bgp *bgp, bool set) +{ + bool send_msg = false; + + if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) + return; + + if (set) { + SET_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_FIB_PENDING); + /* Send msg to zebra for the first instance of bgp enabled + * with suppress fib + */ + if (bgp_suppress_fib_count == 0) + send_msg = true; + bgp_suppress_fib_count++; + } else { + UNSET_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_FIB_PENDING); + bgp_suppress_fib_count--; + + /* Send msg to zebra if there are no instances enabled + * with suppress fib + */ + if (bgp_suppress_fib_count == 0) + send_msg = true; + } + /* Send route notify request to RIB */ + if (send_msg) { + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Sending ZEBRA_ROUTE_NOTIFY_REQUEST"); + + if (zclient) + zebra_route_notify_send(ZEBRA_ROUTE_NOTIFY_REQUEST, + zclient, set); + } +} + /* BGP's cluster-id control. */ int bgp_cluster_id_set(struct bgp *bgp, struct in_addr *cluster_id) { @@ -1054,6 +1094,15 @@ static void peer_free(struct peer *peer) bgp_delete_connected_nexthop(family2afi(peer->su.sa.sa_family), peer); + FOREACH_AFI_SAFI (afi, safi) { + if (peer->filter[afi][safi].advmap.aname) + XFREE(MTYPE_BGP_FILTER_NAME, + peer->filter[afi][safi].advmap.aname); + if (peer->filter[afi][safi].advmap.cname) + XFREE(MTYPE_BGP_FILTER_NAME, + peer->filter[afi][safi].advmap.cname); + } + XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message); XFREE(MTYPE_PEER_DESC, peer->desc); @@ -1081,12 +1130,8 @@ static void peer_free(struct peer *peer) bfd_info_free(&(peer->bfd_info)); - for (afi = AFI_IP; afi < AFI_MAX; afi++) { - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { - bgp_addpath_set_peer_type(peer, afi, safi, - BGP_ADDPATH_NONE); - } - } + FOREACH_AFI_SAFI (afi, safi) + bgp_addpath_set_peer_type(peer, afi, safi, BGP_ADDPATH_NONE); bgp_unlock(peer->bgp); @@ -3382,6 +3427,14 @@ int bgp_delete(struct bgp *bgp) assert(bgp); + /* make sure we withdraw any exported routes */ + vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP, bgp_get_default(), + bgp); + vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP6, bgp_get_default(), + bgp); + + bgp_vpn_leak_unimport(bgp); + hook_call(bgp_inst_delete, bgp); THREAD_OFF(bgp->t_startup); @@ -4505,6 +4558,10 @@ int peer_ebgp_multihop_set(struct peer *peer, int ttl) if (peer->sort == BGP_PEER_IBGP || peer->conf_if) return 0; + /* is there anything to do? */ + if (peer->ttl == ttl) + return 0; + /* see comment in peer_ttl_security_hops_set() */ if (ttl != MAXTTL) { if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 287aeca143..d22fd008d8 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -104,10 +104,6 @@ enum bgp_af_index { #define AF_FOREACH(af) for ((af) = BGP_AF_START; (af) < BGP_AF_MAX; (af)++) -#define FOREACH_AFI_SAFI(afi, safi) \ - for (afi = AFI_IP; afi < AFI_MAX; afi++) \ - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - #define FOREACH_SAFI(safi) \ for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) @@ -455,11 +451,12 @@ struct bgp { #define BGP_FLAG_DELETE_IN_PROGRESS (1 << 22) #define BGP_FLAG_SELECT_DEFER_DISABLE (1 << 23) #define BGP_FLAG_GR_DISABLE_EOR (1 << 24) -#define BGP_FLAG_EBGP_REQUIRES_POLICY (1 << 25) -#define BGP_FLAG_SHOW_NEXTHOP_HOSTNAME (1 << 26) +#define BGP_FLAG_EBGP_REQUIRES_POLICY (1 << 25) +#define BGP_FLAG_SHOW_NEXTHOP_HOSTNAME (1 << 26) /* This flag is set if the instance is in administrative shutdown */ -#define BGP_FLAG_SHUTDOWN (1 << 27) +#define BGP_FLAG_SHUTDOWN (1 << 27) +#define BGP_FLAG_SUPPRESS_FIB_PENDING (1 << 28) enum global_mode GLOBAL_GR_FSM[BGP_GLOBAL_GR_MODE] [BGP_GLOBAL_GR_EVENT_CMD]; @@ -712,6 +709,9 @@ struct afi_safi_info { #define BGP_SELECT_DEFER_DISABLE(bgp) \ (CHECK_FLAG(bgp->flags, BGP_FLAG_SELECT_DEFER_DISABLE)) +#define BGP_SUPPRESS_FIB_ENABLED(bgp) \ + (CHECK_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_FIB_PENDING)) + /* BGP peer-group support. */ struct peer_group { /* Name of the peer-group. */ @@ -1283,6 +1283,8 @@ struct peer { #define PEER_THREAD_WRITES_ON (1U << 0) #define PEER_THREAD_READS_ON (1U << 1) #define PEER_THREAD_KEEPALIVES_ON (1U << 2) +#define PEER_THREAD_SUBGRP_ADV_DELAY (1U << 3) + /* workqueues */ struct work_queue *clear_node_queue; @@ -1507,6 +1509,9 @@ DECLARE_QOBJ_TYPE(peer) || CHECK_FLAG((P)->sflags, PEER_STATUS_PREFIX_OVERFLOW) \ || CHECK_FLAG((P)->bgp->flags, BGP_FLAG_SHUTDOWN)) +#define PEER_ROUTE_ADV_DELAY(peer) \ + (CHECK_FLAG(peer->thread_flags, PEER_THREAD_SUBGRP_ADV_DELAY)) + #define PEER_PASSWORD_MINLEN (1) #define PEER_PASSWORD_MAXLEN (80) @@ -1677,6 +1682,7 @@ struct bgp_nlri { #define BGP_DEFAULT_STALEPATH_TIME 360 #define BGP_DEFAULT_SELECT_DEFERRAL_TIME 360 #define BGP_DEFAULT_RIB_STALE_TIME 500 +#define BGP_DEFAULT_UPDATE_ADVERTISEMENT_TIME 1 /* BGP uptime string length. */ #define BGP_UPTIME_LEN 25 @@ -1853,6 +1859,7 @@ extern int bgp_handle_socket(struct bgp *bgp, struct vrf *vrf, extern void bgp_router_id_zebra_bump(vrf_id_t, const struct prefix *); extern void bgp_router_id_static_set(struct bgp *, struct in_addr); +extern void bgp_suppress_fib_pending_set(struct bgp *bgp, bool set); extern int bgp_cluster_id_set(struct bgp *, struct in_addr *); extern int bgp_cluster_id_unset(struct bgp *); diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c index 2d81a6ce65..f7bbd44512 100644 --- a/bgpd/rfapi/rfapi.c +++ b/bgpd/rfapi/rfapi.c @@ -744,7 +744,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ encaptlv->length = 4; lt = htonl(*lifetime); memcpy(encaptlv->value, <, 4); - attr.vnc_subtlvs = encaptlv; + bgp_attr_set_vnc_subtlvs(&attr, encaptlv); vnc_zlog_debug_verbose( "%s: set Encap Attr Prefix Lifetime to %d", __func__, *lifetime); @@ -754,7 +754,8 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ if (rfp_options) { if (flags & RFAPI_AHR_RFPOPT_IS_VNCTLV) { - + struct bgp_attr_encap_subtlv *vnc_subtlvs = + bgp_attr_get_vnc_subtlvs(&attr); /* * this flag means we're passing a pointer to an * existing encap tlv chain which we should copy. @@ -763,16 +764,15 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ */ encaptlv = encap_tlv_dup( (struct bgp_attr_encap_subtlv *)rfp_options); - if (attr.vnc_subtlvs) { - attr.vnc_subtlvs->next = encaptlv; - } else { - attr.vnc_subtlvs = encaptlv; - } - + if (vnc_subtlvs) + vnc_subtlvs->next = encaptlv; + else + bgp_attr_set_vnc_subtlvs(&attr, encaptlv); } else { struct bgp_tea_options *hop; /* XXX max of one tlv present so far from above code */ - struct bgp_attr_encap_subtlv *tail = attr.vnc_subtlvs; + struct bgp_attr_encap_subtlv *tail = + bgp_attr_get_vnc_subtlvs(&attr); for (hop = rfp_options; hop; hop = hop->next) { @@ -798,11 +798,11 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ /* * add to end of subtlv chain */ - if (tail) { + if (tail) tail->next = encaptlv; - } else { - attr.vnc_subtlvs = encaptlv; - } + else + bgp_attr_set_vnc_subtlvs(&attr, + encaptlv); tail = encaptlv; } } @@ -3688,20 +3688,16 @@ static void rfapi_print_exported(struct bgp *bgp) if (!table) continue; fprintf(stderr, "%s: encap destn=%p\n", __func__, destn); - for (dest = bgp_table_top(table)) - ; - dest; - dest = bgp_route_next(dest)) - { - bpi = bgp_dest_get_bgp_path_info(dest); - if (!bpi) - continue; - fprintf(stderr, "%s: dest=%p\n", __func__, dest); - for (; bpi; bpi = bpi->next) { - rfapiPrintBi((void *)2, - bpi); /* 2 => stderr */ - } - } + for (dest = bgp_table_top(table); dest; + dest = bgp_route_next(dest)) { + bpi = bgp_dest_get_bgp_path_info(dest); + if (!bpi) + continue; + fprintf(stderr, "%s: dest=%p\n", __func__, dest); + for (; bpi; bpi = bpi->next) { + rfapiPrintBi((void *)2, bpi); /* 2 => stderr */ + } + } } } #endif /* defined(DEBUG_RFAPI) */ diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c index e3581addee..3d87b63542 100644 --- a/bgpd/rfapi/rfapi_import.c +++ b/bgpd/rfapi/rfapi_import.c @@ -298,10 +298,9 @@ static wq_item_status rfapi_deferred_close_workfunc(struct work_queue *q, int rfapiGetL2o(struct attr *attr, struct rfapi_l2address_option *l2o) { if (attr) { - struct bgp_attr_encap_subtlv *pEncap; - for (pEncap = attr->vnc_subtlvs; pEncap; + for (pEncap = bgp_attr_get_vnc_subtlvs(attr); pEncap; pEncap = pEncap->next) { if (pEncap->type == BGP_VNC_SUBTLV_TYPE_RFPOPTION) { @@ -358,7 +357,7 @@ int rfapiGetVncLifetime(struct attr *attr, uint32_t *lifetime) if (attr) { - for (pEncap = attr->vnc_subtlvs; pEncap; + for (pEncap = bgp_attr_get_vnc_subtlvs(attr); pEncap; pEncap = pEncap->next) { if (pEncap->type @@ -1337,7 +1336,8 @@ rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix, return NULL; } - for (pEncap = bpi->attr->vnc_subtlvs; pEncap; pEncap = pEncap->next) { + for (pEncap = bgp_attr_get_vnc_subtlvs(bpi->attr); pEncap; + pEncap = pEncap->next) { switch (pEncap->type) { case BGP_VNC_SUBTLV_TYPE_LIFETIME: /* use configured lifetime, not attr lifetime */ diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c index 630a379ec2..d1f335f549 100644 --- a/bgpd/rfapi/rfapi_rib.c +++ b/bgpd/rfapi/rfapi_rib.c @@ -622,7 +622,8 @@ static void rfapiRibBi2Ri(struct bgp_path_info *bpi, struct rfapi_info *ri, ri->lifetime = lifetime; /* This loop based on rfapiRouteInfo2NextHopEntry() */ - for (pEncap = bpi->attr->vnc_subtlvs; pEncap; pEncap = pEncap->next) { + for (pEncap = bgp_attr_get_vnc_subtlvs(bpi->attr); pEncap; + pEncap = pEncap->next) { struct bgp_tea_options *hop; switch (pEncap->type) { diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c index b9a6c4ddc4..40d5111e8c 100644 --- a/bgpd/rfapi/rfapi_vty.c +++ b/bgpd/rfapi/rfapi_vty.c @@ -456,7 +456,8 @@ void rfapiPrintAttrPtrs(void *stream, struct attr *attr) struct vty *vty; void *out; const char *vty_newline; - + struct transit *transit; + struct cluster_list *cluster; char buf[BUFSIZ]; if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) @@ -477,10 +478,14 @@ void rfapiPrintAttrPtrs(void *stream, struct attr *attr) fp(out, " ecommunity=%p, refcnt=%d%s", attr->ecommunity, (attr->ecommunity ? attr->ecommunity->refcnt : 0), HVTYNL); - fp(out, " cluster=%p, refcnt=%d%s", attr->cluster, - (attr->cluster ? attr->cluster->refcnt : 0), HVTYNL); - fp(out, " transit=%p, refcnt=%d%s", attr->transit, - (attr->transit ? attr->transit->refcnt : 0), HVTYNL); + + cluster = bgp_attr_get_cluster(attr); + fp(out, " cluster=%p, refcnt=%d%s", cluster, + (cluster ? cluster->refcnt : 0), HVTYNL); + + transit = bgp_attr_get_transit(attr); + fp(out, " transit=%p, refcnt=%d%s", transit, + (transit ? transit->refcnt : 0), HVTYNL); } /* @@ -591,7 +596,8 @@ void rfapiPrintBi(void *stream, struct bgp_path_info *bpi) } /* RFP option lengths */ - for (pEncap = bpi->attr->vnc_subtlvs; pEncap; pEncap = pEncap->next) { + for (pEncap = bgp_attr_get_vnc_subtlvs(bpi->attr); pEncap; + pEncap = pEncap->next) { if (pEncap->type == BGP_VNC_SUBTLV_TYPE_RFPOPTION) { if (printed_1st_gol) { diff --git a/bgpd/rfapi/vnc_export_bgp.c b/bgpd/rfapi/vnc_export_bgp.c index 11f39b2b82..762cd2596f 100644 --- a/bgpd/rfapi/vnc_export_bgp.c +++ b/bgpd/rfapi/vnc_export_bgp.c @@ -290,7 +290,7 @@ void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct agg_node *rn, info.peer = peer; info.attr = &hattr; ret = route_map_apply(bgp->rfapi_cfg->routemap_export_bgp, - prefix, RMAP_BGP, &info); + prefix, &info); if (ret == RMAP_DENYMATCH) { bgp_attr_flush(&hattr); return; @@ -1033,7 +1033,7 @@ void vnc_direct_bgp_add_nve(struct bgp *bgp, struct rfapi_descriptor *rfd) ret = route_map_apply( rfgn->rfg ->routemap_export_bgp, - p, RMAP_BGP, &info); + p, &info); if (ret == RMAP_DENYMATCH) { bgp_attr_flush(&hattr); continue; @@ -1242,8 +1242,7 @@ static void vnc_direct_add_rn_group_rd(struct bgp *bgp, info.peer = irfd->peer; info.attr = &hattr; - ret = route_map_apply(rfg->routemap_export_bgp, p, RMAP_BGP, - &info); + ret = route_map_apply(rfg->routemap_export_bgp, p, &info); if (ret == RMAP_DENYMATCH) { bgp_attr_flush(&hattr); vnc_zlog_debug_verbose( @@ -1691,8 +1690,7 @@ void vnc_direct_bgp_rh_add_route(struct bgp *bgp, afi_t afi, memset(&info, 0, sizeof(info)); info.peer = peer; info.attr = &hattr; - ret = route_map_apply(hc->routemap_export_bgp, prefix, RMAP_BGP, - &info); + ret = route_map_apply(hc->routemap_export_bgp, prefix, &info); if (ret == RMAP_DENYMATCH) { bgp_attr_flush(&hattr); return; @@ -1917,8 +1915,7 @@ void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi) info.attr = &hattr; ret = route_map_apply( hc->routemap_export_bgp, - dest_p, RMAP_BGP, - &info); + dest_p, &info); if (ret == RMAP_DENYMATCH) { bgp_attr_flush(&hattr); vnc_zlog_debug_verbose( diff --git a/bgpd/rfapi/vnc_import_bgp.c b/bgpd/rfapi/vnc_import_bgp.c index 0b6b39b966..b23c1eda76 100644 --- a/bgpd/rfapi/vnc_import_bgp.c +++ b/bgpd/rfapi/vnc_import_bgp.c @@ -357,7 +357,7 @@ static int process_unicast_route(struct bgp *bgp, /* in */ memset(&info, 0, sizeof(info)); info.peer = peer; info.attr = &hattr; - ret = route_map_apply(rmap, prefix, RMAP_BGP, &info); + ret = route_map_apply(rmap, prefix, &info); if (ret == RMAP_DENYMATCH) { bgp_attr_flush(&hattr); vnc_zlog_debug_verbose( @@ -468,7 +468,7 @@ static void vnc_import_bgp_add_route_mode_resolve_nve_one_bi( plifetime = &lifetime; } - encaptlvs = bpi->attr->vnc_subtlvs; + encaptlvs = bgp_attr_get_vnc_subtlvs(bpi->attr); if (bpi->attr->encap_tunneltype != BGP_ENCAP_TYPE_RESERVED && bpi->attr->encap_tunneltype != BGP_ENCAP_TYPE_MPLS) { opt = &optary[cur_opt++]; @@ -784,7 +784,7 @@ static void vnc_import_bgp_add_route_mode_plain(struct bgp *bgp, memset(&info, 0, sizeof(info)); info.peer = peer; info.attr = &hattr; - ret = route_map_apply(rmap, prefix, RMAP_BGP, &info); + ret = route_map_apply(rmap, prefix, &info); if (ret == RMAP_DENYMATCH) { bgp_attr_flush(&hattr); vnc_zlog_debug_verbose( @@ -977,7 +977,7 @@ static void vnc_import_bgp_add_route_mode_nvegroup( memset(&path, 0, sizeof(path)); path.peer = peer; path.attr = &hattr; - ret = route_map_apply(rmap, prefix, RMAP_BGP, &path); + ret = route_map_apply(rmap, prefix, &path); if (ret == RMAP_DENYMATCH) { bgp_attr_flush(&hattr); vnc_zlog_debug_verbose( diff --git a/doc/developer/building-frr-for-openwrt.rst b/doc/developer/building-frr-for-openwrt.rst index 9bd1296dad..47cf2cbd43 100644 --- a/doc/developer/building-frr-for-openwrt.rst +++ b/doc/developer/building-frr-for-openwrt.rst @@ -51,7 +51,7 @@ to work and it may be needed to run a ``make`` for the entire build environment. Add ``V=s`` to get more debugging output. More information about OpenWrt buildsystem can be found `here -<https://openwrt.org/docs/guide-developer/build-system/use-buildsystem>`_. +<https://openwrt.org/docs/guide-developer/build-system/use-buildsystem>`__. Work with sources ----------------- @@ -59,7 +59,7 @@ Work with sources To update to a newer version, or change other options, you need to edit the ``feeds/packages/frr/Makefile``. More information about working with patches in OpenWrt buildsystem can be found `here -<https://openwrt.org/docs/guide-developer/build-system/use-patches-with-buildsystem>`_. +<https://openwrt.org/docs/guide-developer/build-system/use-patches-with-buildsystem>`__. Usage ----- diff --git a/doc/developer/fuzzing.rst b/doc/developer/fuzzing.rst new file mode 100644 index 0000000000..8a3318745e --- /dev/null +++ b/doc/developer/fuzzing.rst @@ -0,0 +1,164 @@ +.. _fuzzing: + +Fuzzing +======= + +This page describes the fuzzing targets and supported fuzzers available in FRR +and how to use them. Familiarity with fuzzing techniques and tools is assumed. + +Overview +-------- + +It is well known that networked applications tend to be difficult to fuzz on +their network-facing attack surfaces. Approaches involving actual network +transmission tend to be slow and are subject to intermediate devices and +networking stacks which tend to drop fuzzed packets, especially if the fuzzing +surface covers IP itself. Some time was spent on fuzzing FRR this way with some +mediocre results but attention quickly turned towards skipping the actual +networking and instead adding fuzzing targets directly in the packet processing +code for use by more traditional in- and out-of-process fuzzers. Results from +this approach have been very fruitful. + +The patches to add fuzzing targets are kept in a separate git branch. Typically +it is better to keep them in the main branch so they are kept up to date and do +not need to be constantly synchronized with the main codebase. Unfortunately, +changes to FRR to support fuzzing necessarily extend far beyond the +entrypoints. Checksums must be disarmed, interactions with the kernel must be +skipped, sockets and files must be avoided, desired under/overflows must be +marked, etc. There are the usual ``LD_PRELOAD`` libraries to emulate these +things (preeny et al) but FRR is a very kernel-reliant program and these +libraries tend to create annoying problems when used with FRR for whatever +reason. Keeping this code in the main codebase is cluttering, difficult to work +with / around, and runs the risk of accidentally introducing bugs even if +``#ifdef``'d out. Consequently it's in a separate branch that is rebased on +``master`` from time to time. + + +Code +---- + +The git branch with fuzzing targets is located here: + +https://github.com/FRRouting/frr/tree/fuzz + +To build libFuzzer targets, pass ``--enable-libfuzzer`` to ``configure``. +To build AFL targets, compile with ``afl-clang`` as usual. + +Fuzzing with sanitizers is strongly recommended, especially ASAN, which you can +enable by passing ``--enable-address-sanitizer`` to ``configure``. + +Suggested UBSAN flags: ``-fsanitize-recover=unsigned-integer-overflow,implicit-conversion -fsanitize=unsigned-integer-overflow,implicit-conversion,nullability-arg,nullability-assign,nullability-return`` +Recommended cflags: ``-Wno-all -g3 -O3 -funroll-loops`` + +Design +------ + +All fuzzing targets have support for libFuzzer and AFL. This is done by writing +the target as a libFuzzer entrypoint (``LLVMFuzzerTestOneInput()``) and calling +it from the AFL entrypoint in ``main()``. New targets should use this rule. + +When adding AFL entrypoints, it's a good idea to use AFL persistent mode for +better performance. Grep ``bgpd/bgp_main.c`` for ``__AFL_INIT()`` for an +example of how to do this in FRR. Typically it involves moving all internal +daemon setup into a setup function. Then this setup function is called exactly +once for the lifetime of the process. In ``LLVMFuzzerTestOneInput()`` this +means you need to call it at the start of the function protected by a static +boolean that is set to true, since that function is your entrypoint. You also +need to call it prior to ``__AFL_INIT()`` in ``main()`` because ``main()`` is +your entrypoint in the AFL case. + +Adding support to daemons +^^^^^^^^^^^^^^^^^^^^^^^^^ + +This section describes how to add entrypoints to daemons that do not have any +yet. + +Because libFuzzer has its own ``main()`` function, when adding fuzzing support +to a daemon that doesn't have any targets already, ``main()`` needs to be +``#ifdef``'d out like so: + +.. code:: c + + #ifndef FUZZING_LIBFUZZER + + int main(int argc, char **argv) + { + ... + } + + #endif /* FUZZING_LIBFUZZER */ + + +The ``FUZZING_LIBFUZZER`` macro is set by ``--enable-libfuzzer``. + +Because libFuzzer can only be linked into daemons that have +``LLVMFuzzerTestOneInput()`` implemented, we can't pass ``-fsanitize=fuzzer`` +to all daemons in ``AM_CFLAGS``. It needs to go into a variable specific to +each daemon. Since it can be thought of as a kind of sanitizer, for daemons +that have libFuzzer support there are now individual flags variables for those +daemons named ``DAEMON_SAN_FLAGS`` (e.g. ``BGPD_SAN_FLAGS``, +``ZEBRA_SAN_FLAGS``). This variable has the contents of the generic +``SAN_FLAGS`` plus any fuzzing-related flags. It is used in daemons' +``subdir.am`` in place of ``SAN_FLAGS``. Daemons that don't support libFuzzer +still use ``SAN_FLAGS``. If you want to add fuzzing support to a daemon you +need to do this flag variable conversion; look at ``configure.ac`` for +examples, it is fairly straightforward. Remember to update ``subdir.am`` to use +the new variable. + +Do note that when fuzzing is enabled, ``SAN_FLAGS`` gains +``-fsanitize=fuzzer-no-link``; the result is that all daemons are instrumented +for fuzzing but only the ones with ``LLVMFuzzerTestOneInput()`` actually get +linked with libFuzzer. + + +Targets +------- + +A given daemon can have lots of different paths that are interesting to fuzz. +There's not really a great way to handle this, most fuzzers assume the program +has one entrypoint. The approach taken in FRR for multiple entrypoints is to +control which path is taken within ``LLVMFuzzerTestOneInput()`` using +``#ifdef`` and passing whatever controlling macro definition you want. Take a +look at that function for the daemon you're interested in fuzzing, pick the +target, add ``#define MY_TARGET 1`` somewhere before the ``#ifdef`` switch, +recompile. + +.. list-table:: Fuzzing Targets + + * - Daemon + - Target + - Fuzzers + * - bgpd + - packet parser + - libfuzzer, afl + * - ospfd + - packet parser + - libfuzzer, afl + * - pimd + - packet parser + - libfuzzer, afl + * - vrrpd + - packet parser + - libfuzzer, afl + * - vrrpd + - zapi parser + - libfuzzer, afl + * - zebra + - netlink + - libfuzzer, afl + * - zebra + - zserv / zapi + - libfuzzer, afl + + +Fuzzer Notes +------------ + +Some interesting seed corpuses for various daemons are available `here +<https://github.com/qlyoung/frr-fuzz/tree/master/samples>`_. + +For libFuzzer, you need to pass ``-rss_limit_mb=0`` if you are fuzzing with +ASAN enabled, as you should. + +For AFL, afl++ is strongly recommended; afl proper isn't really maintained +anymore. diff --git a/doc/developer/index.rst b/doc/developer/index.rst index 1ba0f31c8a..5a7da806ff 100644 --- a/doc/developer/index.rst +++ b/doc/developer/index.rst @@ -9,6 +9,7 @@ FRRouting Developer's Guide packaging process-architecture library + fuzzing tracing testing bgpd diff --git a/doc/user/basic.rst b/doc/user/basic.rst index 0bdcccaf74..7a450bec53 100644 --- a/doc/user/basic.rst +++ b/doc/user/basic.rst @@ -26,7 +26,7 @@ forms the initial command set for a routing beast as it is starting. Config files are generally found in |INSTALL_PREFIX_ETC|. Config Methods -^^^^^^^^^^^^^^ +-------------- There are two ways of configuring FRR. diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 3572734ba9..0a562e1edf 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -962,6 +962,56 @@ Networks traditional did not check for existence. For versions 7.4 and beyond both traditional and datacenter the network must exist. +.. _bgp-ipv6-support: + +IPv6 Support +------------ + +.. index:: [no] neighbor A.B.C.D activate +.. clicmd:: [no] neighbor A.B.C.D activate + + This configuration modifies whether to enable an address family for a + specific neighbor. By default only the IPv4 unicast address family is + enabled. + + .. code-block:: frr + + router bgp 1 + address-family ipv6 unicast + neighbor 2001:0DB8::1 activate + network 2001:0DB8:5009::/64 + exit-address-family + + This configuration example says that network 2001:0DB8:5009::/64 will be + announced and enables the neighbor 2001:0DB8::1 to receive this announcement. + +.. index:: [no] bgp default ipv4-unicast +.. clicmd:: [no] bgp default ipv4-unicast + + By default, only the IPv4 unicast address family is announced to all + neighbors. Using the 'no bgp default ipv4-unicast' configuration overrides + this default so that all address families need to be enabled explicitly. + + .. code-block:: frr + + router bgp 1 + no bgp default ipv4-unicast + neighbor 10.10.10.1 remote-as 2 + neighbor 2001:0DB8::1 remote-as 3 + address-family ipv4 unicast + neighbor 10.10.10.1 activate + network 192.168.1.0/24 + exit-address-family + address-family ipv6 unicast + neighbor 2001:0DB8::1 activate + network 2001:0DB8:5009::/64 + exit-address-family + + This configuration demonstrates how the 'no bgp default ipv4-unicast' might + be used in a setup with two upstreams where each of the upstreams should only + receive either IPv4 or IPv6 annocuments. + + .. _bgp-route-aggregation: Route Aggregation @@ -1303,10 +1353,10 @@ Configuring Peers Optionally you can specify a shutdown message `MSG`. - Also, you can specify optionally _rtt_ in milliseconds to automatically + Also, you can specify optionally ``rtt`` in milliseconds to automatically shutdown the peer if round-trip-time becomes higher than defined. - Additional _count_ parameter is the number of keepalive messages to count + Additional ``count`` parameter is the number of keepalive messages to count before shutdown the peer if round-trip-time becomes higher than defined. .. index:: [no] neighbor PEER disable-connected-check @@ -1420,7 +1470,7 @@ Configuring Peers granular and offers much smarter matching criterion than number of received prefixes, making it more suited to implementing policy. - If _force_ is set, then ALL prefixes are counted for maximum instead of + If ``force`` is set, then ALL prefixes are counted for maximum instead of accepted only. This is useful for cases where an inbound filter is applied, but you want maximum-prefix to act on ALL (including filtered) prefixes. This option requires `soft-reconfiguration inbound` to be enabled for the peer. @@ -3122,16 +3172,16 @@ displays IPv6 routing table. Total number of prefixes 1 - If _wide_ option is specified, then the prefix table's width is increased + If ``wide`` option is specified, then the prefix table's width is increased to fully display the prefix and the nexthop. This is especially handy dealing with IPv6 prefixes and if :clicmd:`[no] bgp default show-nexthop-hostname` is enabled. - If _all_ option is specified, _ip_ keyword is ignored, show bgp all and + If ``all`` option is specified, ``ip`` keyword is ignored, show bgp all and show ip bgp all commands display routes for all AFIs and SAFIs. - If _json_ option is specified, output is displayed in JSON format. + If ``json`` option is specified, output is displayed in JSON format. Some other commands provide additional options for filtering the output. @@ -3225,18 +3275,18 @@ structure is extended with :clicmd:`show bgp [afi] [safi]`. from neighbor or filtered routes received from neighbor based on the option specified. - If _wide_ option is specified, then the prefix table's width is increased + If ``wide`` option is specified, then the prefix table's width is increased to fully display the prefix and the nexthop. This is especially handy dealing with IPv6 prefixes and if :clicmd:`[no] bgp default show-nexthop-hostname` is enabled. - If _all_ option is specified, _ip_ keyword is ignored and, + If ``all`` option is specified, ``ip`` keyword is ignored and, routes displayed for all AFIs and SAFIs. - if afi is specified, with _all_ option, routes will be displayed for + if afi is specified, with ``all`` option, routes will be displayed for each SAFI in the selcted AFI - If _json_ option is specified, output is displayed in JSON format. + If ``json`` option is specified, output is displayed in JSON format. .. _bgp-display-routes-by-community: @@ -3270,18 +3320,18 @@ attribute. match the specified community list. When `exact-match` is specified, it displays only routes that have an exact match. - If _wide_ option is specified, then the prefix table's width is increased + If ``wide`` option is specified, then the prefix table's width is increased to fully display the prefix and the nexthop. This is especially handy dealing with IPv6 prefixes and if :clicmd:`[no] bgp default show-nexthop-hostname` is enabled. - If _all_ option is specified, _ip_ keyword is ignored and, + If ``all`` option is specified, ``ip`` keyword is ignored and, routes displayed for all AFIs and SAFIs. - if afi is specified, with _all_ option, routes will be displayed for + if afi is specified, with ``all`` option, routes will be displayed for each SAFI in the selcted AFI - If _json_ option is specified, output is displayed in JSON format. + If ``json`` option is specified, output is displayed in JSON format. .. _bgp-display-routes-by-lcommunity: @@ -3412,6 +3462,49 @@ starting the daemon and the configuration gets saved, the option will persist unless removed from the configuration with the negating command prior to the configuration write operation. +.. _bgp-suppress-fib: + +Suppressing routes not installed in FIB +======================================= + +The FRR implementation of BGP advertises prefixes learnt from a peer to other +peers even if the routes do not get installed in the FIB. There can be +scenarios where the hardware tables in some of the routers (along the path from +the source to destination) is full which will result in all routes not getting +installed in the FIB. If these routes are advertised to the downstream routers +then traffic will start flowing and will be dropped at the intermediate router. + +The solution is to provide a configurable option to check for the FIB install +status of the prefixes and advertise to peers if the prefixes are successfully +installed in the FIB. The advertisement of the prefixes are suppressed if it is +not installed in FIB. + +The following conditions apply will apply when checking for route installation +status in FIB: + +1. The advertisement or suppression of routes based on FIB install status + applies only for newly learnt routes from peer (routes which are not in + BGP local RIB). +2. If the route received from peer already exists in BGP local RIB and route + attributes have changed (best path changed), the old path is deleted and + new path is installed in FIB. The FIB install status will not have any + effect. Therefore only when the route is received first time the checks + apply. +3. The feature will not apply for routes learnt through other means like + redistribution to bgp from other protocols. This is applicable only to + peer learnt routes. +4. If a route is installed in FIB and then gets deleted from the dataplane, + then routes will not be withdrawn from peers. This will be considered as + dataplane issue. +5. The feature will slightly increase the time required to advertise the routes + to peers since the route install status needs to be received from the FIB +6. If routes are received by the peer before the configuration is applied, then + the bgp sessions need to be reset for the configuration to take effect. +7. If the route which is already installed in dataplane is removed for some + reason, sending withdraw message to peers is not currently supported. + +.. index:: [no] bgp suppress-fib-pending +.. clicmd:: [no] bgp suppress-fib-pending .. _routing-policy: diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst index 6295ba9293..dd53d8f8b4 100644 --- a/doc/user/ospf6d.rst +++ b/doc/user/ospf6d.rst @@ -179,10 +179,11 @@ Showing OSPF6 information To see OSPF interface configuration like costs. -.. index:: show ipv6 ospf6 neighbor -.. clicmd:: show ipv6 ospf6 neighbor +.. index:: show ipv6 ospf6 neighbor [json] +.. clicmd:: show ipv6 ospf6 neighbor [json] - Shows state and chosen (Backup) DR of neighbor. + Shows state and chosen (Backup) DR of neighbor. JSON output can be + obtained by appending 'json' at the end. .. index:: show ipv6 ospf6 request-list A.B.C.D .. clicmd:: show ipv6 ospf6 request-list A.B.C.D diff --git a/doc/user/vrrp.rst b/doc/user/vrrp.rst index 8ab050e9a0..cb70da3f3b 100644 --- a/doc/user/vrrp.rst +++ b/doc/user/vrrp.rst @@ -503,6 +503,7 @@ The following configuration is then generated for you: vrrp 5 ip 10.0.2.16 vrrp 5 ipv6 2001:db8::370:7334 + VRRP is automatically activated. Global defaults, if set, are applied. You can then edit this configuration with **vtysh** as needed, and commit it by @@ -516,6 +517,7 @@ My virtual routers are not seeing each others' advertisements ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Check: + - Is your kernel at least 5.1? - Did you set the macvlan devices to ``bridge`` mode? - If using IPv4 virtual addresses, does the parent of the macvlan devices have diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst index 624e3cfe1a..5c7f4ac773 100644 --- a/doc/user/zebra.rst +++ b/doc/user/zebra.rst @@ -72,6 +72,19 @@ Besides the common invocation options (:ref:`common-invocation-options`), the option and we will use Route Replace Semantics instead of delete than add. +.. option:: --asic-offload [notify_on_offload|notify_on_ack] + + The linux kernel has the ability to use asic-offload ( see switchdev + development ). When the operator knows that FRR will be working in + this way, allow them to specify this with FRR. At this point this + code only supports asynchronous notification of the offload state. + In other words the initial ACK received for linux kernel installation + does not give zebra any data about what the state of the offload + is. This option takes the optional paramegers notify_on_offload + or notify_on_ack. This signals to zebra to notify upper level + protocols about route installation/update on ack received from + the linux kernel or from offload notification. + .. _interface-commands: Configuration Addresses behaviour diff --git a/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c index 473cc75a2a..0795fbd6df 100644 --- a/eigrpd/eigrp_zebra.c +++ b/eigrpd/eigrp_zebra.c @@ -88,7 +88,8 @@ static int eigrp_zebra_route_notify_owner(ZAPI_CALLBACK_ARGS) enum zapi_route_notify_owner note; uint32_t table; - if (!zapi_route_notify_decode(zclient->ibuf, &p, &table, ¬e)) + if (!zapi_route_notify_decode(zclient->ibuf, &p, &table, ¬e, NULL, + NULL)) return -1; return 0; diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 9b814c92de..74a0d795ab 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -319,6 +319,7 @@ enum rt_scope_t { #define RTM_F_FIB_MATCH 0x2000 /* return full fib lookup match */ #define RTM_F_OFFLOAD 0x4000 /* route is offloaded */ #define RTM_F_TRAP 0x8000 /* route is trapping packets */ +#define RTM_F_OFFLOAD_FAILED 0x10000 /* route offload failed */ /* Reserved table identifiers */ diff --git a/isisd/isis_redist.c b/isisd/isis_redist.c index e6c7a734bd..240be27cf3 100644 --- a/isisd/isis_redist.c +++ b/isisd/isis_redist.c @@ -167,8 +167,7 @@ static void isis_redist_update_ext_reach(struct isis_area *area, int level, area_info.metric = redist->metric; if (redist->map_name) { - map_ret = - route_map_apply(redist->map, p, RMAP_ISIS, &area_info); + map_ret = route_map_apply(redist->map, p, &area_info); if (map_ret == RMAP_DENYMATCH) area_info.distance = 255; } @@ -380,6 +379,19 @@ static void isis_redist_update_zebra_subscriptions(struct isis *isis) } } +void isis_redist_free(struct isis *isis) +{ + int i; + + for (i = 0; i < REDIST_PROTOCOL_COUNT; i++) { + if (!isis->ext_info[i]) + continue; + + route_table_finish(isis->ext_info[i]); + isis->ext_info[i] = NULL; + } +} + void isis_redist_set(struct isis_area *area, int level, int family, int type, uint32_t metric, const char *routemap, int originate_type) { diff --git a/isisd/isis_redist.h b/isisd/isis_redist.h index 0d2dc6a803..afce922240 100644 --- a/isisd/isis_redist.h +++ b/isisd/isis_redist.h @@ -62,4 +62,5 @@ void isis_redist_set(struct isis_area *area, int level, int family, int type, uint32_t metric, const char *routemap, int originate_type); void isis_redist_unset(struct isis_area *area, int level, int family, int type); +void isis_redist_free(struct isis *isis); #endif diff --git a/isisd/isis_routemap.c b/isisd/isis_routemap.c index 902528e1bb..db0f2fd8be 100644 --- a/isisd/isis_routemap.c +++ b/isisd/isis_routemap.c @@ -49,14 +49,10 @@ #include "isis_routemap.h" static enum route_map_cmd_result_t -route_match_ip_address(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_address(void *rule, const struct prefix *prefix, void *object) { struct access_list *alist; - if (type != RMAP_ISIS) - return RMAP_NOMATCH; - alist = access_list_lookup(AFI_IP, (char *)rule); if (access_list_apply(alist, prefix) != FILTER_DENY) return RMAP_MATCH; @@ -85,13 +81,10 @@ static const struct route_map_rule_cmd route_match_ip_address_cmd = { static enum route_map_cmd_result_t route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { struct prefix_list *plist; - if (type != RMAP_ISIS) - return RMAP_NOMATCH; - plist = prefix_list_lookup(AFI_IP, (char *)rule); if (prefix_list_apply(plist, prefix) != PREFIX_DENY) return RMAP_MATCH; @@ -120,14 +113,10 @@ static const struct route_map_rule_cmd /* ------------------------------------------------------------*/ static enum route_map_cmd_result_t -route_match_ipv6_address(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object) { struct access_list *alist; - if (type != RMAP_ISIS) - return RMAP_NOMATCH; - alist = access_list_lookup(AFI_IP6, (char *)rule); if (access_list_apply(alist, prefix) != FILTER_DENY) return RMAP_MATCH; @@ -156,13 +145,10 @@ static const struct route_map_rule_cmd route_match_ipv6_address_cmd = { static enum route_map_cmd_result_t route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { struct prefix_list *plist; - if (type != RMAP_ISIS) - return RMAP_NOMATCH; - plist = prefix_list_lookup(AFI_IP6, (char *)rule); if (prefix_list_apply(plist, prefix) != PREFIX_DENY) return RMAP_MATCH; @@ -191,18 +177,16 @@ static const struct route_map_rule_cmd /* ------------------------------------------------------------*/ static enum route_map_cmd_result_t -route_set_metric(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_metric(void *rule, const struct prefix *prefix, void *object) { uint32_t *metric; struct isis_ext_info *info; - if (type == RMAP_ISIS) { - metric = rule; - info = object; + metric = rule; + info = object; + + info->metric = *metric; - info->metric = *metric; - } return RMAP_OKAY; } diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 5480a1b339..19cacde4fe 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -1727,6 +1727,11 @@ static struct isis_spf_run *isis_run_spf_arg(struct isis_area *area, int level) return run; } +void isis_spf_timer_free(void *run) +{ + XFREE(MTYPE_ISIS_SPF_RUN, run); +} + int _isis_spf_schedule(struct isis_area *area, int level, const char *func, const char *file, int line) { diff --git a/isisd/isis_spf.h b/isisd/isis_spf.h index a9a14fc75e..ad15d3e3c7 100644 --- a/isisd/isis_spf.h +++ b/isisd/isis_spf.h @@ -78,4 +78,5 @@ struct isis_spftree *isis_run_hopcount_spf(struct isis_area *area, uint8_t *sysid, struct isis_spftree *spftree); +void isis_spf_timer_free(void *run); #endif /* _ZEBRA_ISIS_SPF_H */ diff --git a/isisd/isisd.c b/isisd/isisd.c index 057ede0e38..950cdc281f 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -442,7 +442,11 @@ void isis_area_destroy(struct isis_area *area) spftree_area_del(area); + if (area->spf_timer[0]) + isis_spf_timer_free(THREAD_ARG(area->spf_timer[0])); thread_cancel(&area->spf_timer[0]); + if (area->spf_timer[1]) + isis_spf_timer_free(THREAD_ARG(area->spf_timer[1])); thread_cancel(&area->spf_timer[1]); spf_backoff_free(area->spf_delay_ietf[0]); @@ -583,6 +587,7 @@ void isis_finish(struct isis *isis) isis_vrf_unlink(isis, vrf); } + isis_redist_free(isis); list_delete(&isis->area_list); list_delete(&isis->init_circ_list); XFREE(MTYPE_ISIS, isis); @@ -2375,6 +2380,9 @@ static void area_resign_level(struct isis_area *area, int level) } } + if (area->spf_timer[level - 1]) + isis_spf_timer_free(THREAD_ARG(area->spf_timer[level - 1])); + thread_cancel(&area->spf_timer[level - 1]); sched_debug( diff --git a/lib/command.c b/lib/command.c index 7d335e1c36..87110157f6 100644 --- a/lib/command.c +++ b/lib/command.c @@ -154,7 +154,8 @@ static bool vty_check_node_for_xpath_decrement(enum node_type target_node, || node == BGP_IPV4M_NODE || node == BGP_IPV6M_NODE || node == BGP_VPNV4_NODE || node == BGP_VPNV6_NODE || node == BGP_EVPN_NODE || node == BGP_IPV4L_NODE - || node == BGP_IPV6L_NODE )) + || node == BGP_IPV6L_NODE || node == BGP_FLOWSPECV4_NODE + || node == BGP_FLOWSPECV6_NODE)) return false; return true; @@ -455,7 +455,8 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_NEIGH_DISCOVER), DESC_ENTRY(ZEBRA_NHG_ADD), DESC_ENTRY(ZEBRA_NHG_DEL), - DESC_ENTRY(ZEBRA_NHG_NOTIFY_OWNER)}; + DESC_ENTRY(ZEBRA_NHG_NOTIFY_OWNER), + DESC_ENTRY(ZEBRA_ROUTE_NOTIFY_REQUEST)}; #undef DESC_ENTRY static const struct zebra_desc_table unknown = {0, "unknown", '?'}; diff --git a/lib/routemap.c b/lib/routemap.c index 0eb54a4794..004beb3628 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -1530,8 +1530,7 @@ enum rmap_compile_rets route_map_delete_set(struct route_map_index *index, static enum route_map_cmd_result_t route_map_apply_match(struct route_map_rule_list *match_list, - const struct prefix *prefix, route_map_object_t type, - void *object) + const struct prefix *prefix, void *object) { enum route_map_cmd_result_t ret = RMAP_NOMATCH; struct route_map_rule *match; @@ -1555,7 +1554,7 @@ route_map_apply_match(struct route_map_rule_list *match_list, * If all result in NOOP, end-result is NOOP. */ ret = (*match->cmd->func_apply)(match->value, prefix, - type, object); + object); /* * If the consolidated result of func_apply is: @@ -1647,9 +1646,10 @@ static struct list *route_map_get_index_list(struct route_node **rn, /* * This function returns the route-map index that best matches the prefix. */ -static struct route_map_index * -route_map_get_index(struct route_map *map, const struct prefix *prefix, - route_map_object_t type, void *object, uint8_t *match_ret) +static struct route_map_index *route_map_get_index(struct route_map *map, + const struct prefix *prefix, + void *object, + uint8_t *match_ret) { int ret = 0; struct list *candidate_rmap_list = NULL; @@ -1695,7 +1695,7 @@ route_map_get_index(struct route_map *map, const struct prefix *prefix, break; ret = route_map_apply_match(&index->match_list, prefix, - type, object); + object); if (ret == RMAP_MATCH) { *match_ret = ret; @@ -2369,8 +2369,7 @@ void route_map_notify_pentry_dependencies(const char *affected_name, We need to make sure our route-map processing matches the above */ route_map_result_t route_map_apply(struct route_map *map, - const struct prefix *prefix, - route_map_object_t type, void *object) + const struct prefix *prefix, void *object) { static int recursion = 0; enum route_map_cmd_result_t match_ret = RMAP_NOMATCH; @@ -2397,7 +2396,7 @@ route_map_result_t route_map_apply(struct route_map *map, if ((!map->optimization_disabled) && (map->ipv4_prefix_table || map->ipv6_prefix_table)) { - index = route_map_get_index(map, prefix, type, object, + index = route_map_get_index(map, prefix, object, (uint8_t *)&match_ret); if (index) { if (rmap_debug) @@ -2431,7 +2430,7 @@ route_map_result_t route_map_apply(struct route_map *map, index->applied++; /* Apply this index. */ match_ret = route_map_apply_match(&index->match_list, - prefix, type, object); + prefix, object); if (rmap_debug) { zlog_debug( "Route-map: %s, sequence: %d, prefix: %pFX, result: %s", @@ -2489,9 +2488,8 @@ route_map_result_t route_map_apply(struct route_map *map, * set succeeded or not. So, ignore * return code. */ - (void) (*set->cmd->func_apply)( - set->value, prefix, type, - object); + (void)(*set->cmd->func_apply)( + set->value, prefix, object); /* Call another route-map if available */ if (index->nextrm) { @@ -2504,8 +2502,7 @@ route_map_result_t route_map_apply(struct route_map *map, { recursion++; ret = route_map_apply( - nextrm, prefix, type, - object); + nextrm, prefix, object); recursion--; } diff --git a/lib/routemap.h b/lib/routemap.h index 64da4b87ef..3e208c8cb5 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -68,17 +68,6 @@ enum route_map_cmd_result_t { RMAP_ERROR }; - -typedef enum { - RMAP_RIP, - RMAP_RIPNG, - RMAP_OSPF, - RMAP_OSPF6, - RMAP_BGP, - RMAP_ZEBRA, - RMAP_ISIS, -} route_map_object_t; - typedef enum { RMAP_EXIT, RMAP_GOTO, RMAP_NEXT } route_map_end_t; typedef enum { @@ -117,7 +106,6 @@ struct route_map_rule_cmd { /* Function for value set or match. */ enum route_map_cmd_result_t (*func_apply)(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object); /* Compile argument and return result as void *. */ @@ -299,7 +287,6 @@ struct route_map *route_map_lookup_warn_noexist(struct vty *vty, const char *nam /* Apply route map to the object. */ extern route_map_result_t route_map_apply(struct route_map *map, const struct prefix *prefix, - route_map_object_t object_type, void *object); extern void route_map_add_hook(void (*func)(const char *)); diff --git a/lib/sigevent.c b/lib/sigevent.c index de9e1f5410..8d583096f6 100644 --- a/lib/sigevent.c +++ b/lib/sigevent.c @@ -250,6 +250,8 @@ core_handler(int signo, siginfo_t *siginfo, void *context) /* dump memory stats on core */ log_memstats(stderr, "core_handler"); + + zlog_tls_buffer_fini(); abort(); } diff --git a/lib/skiplist.c b/lib/skiplist.c index 2bef18f525..b79dfa6772 100644 --- a/lib/skiplist.c +++ b/lib/skiplist.c @@ -74,7 +74,6 @@ DEFINE_MTYPE_STATIC(LIB, SKIP_LIST_NODE, "Skip Node") static int randomsLeft; static int randomBits; -static struct skiplist *skiplist_last_created; /* debugging hack */ #if 1 #define CHECKLAST(sl) \ @@ -150,8 +149,6 @@ struct skiplist *skiplist_new(int flags, if (del) new->del = del; - skiplist_last_created = new; /* debug */ - return new; } @@ -586,7 +583,8 @@ void skiplist_debug(struct vty *vty, struct skiplist *l) int i; if (!l) - l = skiplist_last_created; + return; + vty_out(vty, "Skiplist %p has max level %d\n", l, l->level); for (i = l->level; i >= 0; --i) vty_out(vty, " @%d: %ld\n", i, diff --git a/lib/thread.c b/lib/thread.c index db53e267f8..e71fd74bd9 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -115,10 +115,9 @@ static void vty_out_cpu_thread_history(struct vty *vty, struct cpu_thread_history *a) { vty_out(vty, "%5zu %10zu.%03zu %9zu %8zu %9zu %8zu %9zu", - (size_t)a->total_active, a->cpu.total / 1000, - a->cpu.total % 1000, (size_t)a->total_calls, - (size_t)(a->cpu.total / a->total_calls), a->cpu.max, - (size_t)(a->real.total / a->total_calls), a->real.max); + a->total_active, a->cpu.total / 1000, a->cpu.total % 1000, + a->total_calls, (a->cpu.total / a->total_calls), a->cpu.max, + (a->real.total / a->total_calls), a->real.max); vty_out(vty, " %c%c%c%c%c %s\n", a->types & (1 << THREAD_READ) ? 'R' : ' ', a->types & (1 << THREAD_WRITE) ? 'W' : ' ', diff --git a/lib/thread.h b/lib/thread.h index 682a17b9f3..eb1b107e7b 100644 --- a/lib/thread.h +++ b/lib/thread.h @@ -115,8 +115,8 @@ struct thread { struct cpu_thread_history { int (*func)(struct thread *); - atomic_uint_fast32_t total_calls; - atomic_uint_fast32_t total_active; + atomic_size_t total_calls; + atomic_size_t total_active; struct time_stats { atomic_size_t total, max; } real; @@ -43,7 +43,7 @@ enum { IFLA_VRF_UNSPEC, IFLA_VRF_TABLE, __IFLA_VRF_MAX }; #endif #define VRF_NAMSIZ 36 -#define NS_NAMSIZ 16 +#define NS_NAMSIZ 36 /* * The command strings diff --git a/lib/zclient.c b/lib/zclient.c index d0144279e5..bab1acf667 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -1494,9 +1494,12 @@ stream_failure: bool zapi_route_notify_decode(struct stream *s, struct prefix *p, uint32_t *tableid, - enum zapi_route_notify_owner *note) + enum zapi_route_notify_owner *note, + afi_t *afi, safi_t *safi) { uint32_t t; + afi_t afi_val; + safi_t safi_val; STREAM_GET(note, s, sizeof(*note)); @@ -1504,9 +1507,16 @@ bool zapi_route_notify_decode(struct stream *s, struct prefix *p, STREAM_GETC(s, p->prefixlen); STREAM_GET(&p->u.prefix, s, prefix_blen(p)); STREAM_GETL(s, t); + STREAM_GETC(s, afi_val); + STREAM_GETC(s, safi_val); *tableid = t; + if (afi) + *afi = afi_val; + if (safi) + *safi = safi_val; + return true; stream_failure: @@ -1815,6 +1825,22 @@ int zebra_redistribute_default_send(int command, struct zclient *zclient, return zclient_send_message(zclient); } +/* Send route notify request to zebra */ +int zebra_route_notify_send(int command, struct zclient *zclient, bool set) +{ + struct stream *s; + + s = zclient->obuf; + stream_reset(s); + + zclient_create_header(s, command, 0); + stream_putc(s, !!set); + + stream_putw_at(s, 0, stream_get_endp(s)); + + return zclient_send_message(zclient); +} + /* Get prefix in ZServ format; family should be filled in on prefix */ static int zclient_stream_get_prefix(struct stream *s, struct prefix *p) { diff --git a/lib/zclient.h b/lib/zclient.h index 80dca3fc56..3c80ba7efa 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -218,6 +218,7 @@ typedef enum { ZEBRA_OPAQUE_REGISTER, ZEBRA_OPAQUE_UNREGISTER, ZEBRA_NEIGH_DISCOVER, + ZEBRA_ROUTE_NOTIFY_REQUEST, } zebra_message_types_t; enum zebra_error_types { @@ -513,6 +514,13 @@ struct zapi_route { * offload situation. */ #define ZEBRA_FLAG_OFFLOADED 0x100 +/* + * This flag tells everyone that the route has + * failed offloading. + * This flag makes no sense unless you are in an asic + * offload situation. + */ +#define ZEBRA_FLAG_OFFLOAD_FAILED 0x200 /* The older XXX_MESSAGE flags live here */ uint32_t message; @@ -778,6 +786,10 @@ extern int zebra_redistribute_send(int command, struct zclient *, afi_t, extern int zebra_redistribute_default_send(int command, struct zclient *zclient, afi_t afi, vrf_id_t vrf_id); +/* Send route notify request to zebra */ +extern int zebra_route_notify_send(int command, struct zclient *zclient, + bool set); + /* If state has changed, update state and call zebra_redistribute_send. */ extern void zclient_redistribute(int command, struct zclient *, afi_t, int type, unsigned short instance, vrf_id_t vrf_id); @@ -910,7 +922,8 @@ bool zapi_nhg_notify_decode(struct stream *s, uint32_t *id, enum zapi_nhg_notify_owner *note); bool zapi_route_notify_decode(struct stream *s, struct prefix *p, uint32_t *tableid, - enum zapi_route_notify_owner *note); + enum zapi_route_notify_owner *note, + afi_t *afi, safi_t *safi); bool zapi_rule_notify_decode(struct stream *s, uint32_t *seqno, uint32_t *priority, uint32_t *unique, char *ifname, enum zapi_rule_notify_owner *note); diff --git a/lib/zebra.h b/lib/zebra.h index 14d66d6627..ded44ac636 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -359,6 +359,10 @@ typedef enum { SAFI_MAX = 8 } safi_t; +#define FOREACH_AFI_SAFI(afi, safi) \ + for (afi = AFI_IP; afi < AFI_MAX; afi++) \ + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + /* Default Administrative Distance of each protocol. */ #define ZEBRA_KERNEL_DISTANCE_DEFAULT 0 #define ZEBRA_CONNECT_DISTANCE_DEFAULT 0 diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c index 2bc2d91597..e7d35b90ff 100644 --- a/nhrpd/nhrp_route.c +++ b/nhrpd/nhrp_route.c @@ -350,10 +350,22 @@ void nhrp_zebra_init(void) zclient_init(zclient, ZEBRA_ROUTE_NHRP, 0, &nhrpd_privs); } +static void nhrp_table_node_cleanup(struct route_table *table, + struct route_node *node) +{ + if (!node->info) + return; + + XFREE(MTYPE_NHRP_ROUTE, node->info); +} + void nhrp_zebra_terminate(void) { zclient_stop(zclient); zclient_free(zclient); + + zebra_rib[AFI_IP]->cleanup = nhrp_table_node_cleanup; + zebra_rib[AFI_IP6]->cleanup = nhrp_table_node_cleanup; route_table_finish(zebra_rib[AFI_IP]); route_table_finish(zebra_rib[AFI_IP6]); } diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c index f087289df6..c71b30a2d4 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -196,7 +196,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, if (ADV_ROUTER_IN_PREFIX(&route->prefix) == area->ospf6->router_id) { zlog_debug( - "%s: Skipping ASBR announcement for ABR (%pFX)", + "%s: Skipping ASBR announcement for ABR (%pI4)", __func__, &ADV_ROUTER_IN_PREFIX(&route->prefix)); return 0; @@ -208,7 +208,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, || IS_OSPF6_DEBUG_ORIGINATE(INTER_ROUTER)) { is_debug++; zlog_debug( - "Originating summary in area %s for ASBR %pFX", + "Originating summary in area %s for ASBR %pI4", area->name, &ADV_ROUTER_IN_PREFIX(&route->prefix)); } @@ -225,9 +225,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, if (is_debug) zlog_debug( "%s: route %pFX with cost %u is not best, ignore.", - __func__, - &ADV_ROUTER_IN_PREFIX( - &route->prefix), + __func__, &route->prefix, route->path.cost); return 0; } @@ -405,8 +403,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, if (is_debug) zlog_debug( "prefix %pFX was denied by export list", - &ADV_ROUTER_IN_PREFIX( - &route->prefix)); + &route->prefix); return 0; } } @@ -418,7 +415,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, if (is_debug) zlog_debug( "prefix %pFX was denied by filter-list out", - &ADV_ROUTER_IN_PREFIX(&route->prefix)); + &route->prefix); return 0; } diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c index c053716f26..1d222d5568 100644 --- a/ospf6d/ospf6_asbr.c +++ b/ospf6d/ospf6_asbr.c @@ -1095,8 +1095,7 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex, tinfo.ifindex = ifindex; tinfo.tag = tag; - ret = route_map_apply(ospf6->rmap[type].map, prefix, RMAP_OSPF6, - &troute); + ret = route_map_apply(ospf6->rmap[type].map, prefix, &troute); if (ret == RMAP_DENYMATCH) { if (IS_OSPF6_DEBUG_ASBR) zlog_debug("Denied by route-map \"%s\"", @@ -1400,14 +1399,11 @@ static void ospf6_redistribute_show_config(struct vty *vty, struct ospf6 *ospf6) static enum route_map_cmd_result_t ospf6_routemap_rule_match_address_prefixlist(void *rule, const struct prefix *prefix, - route_map_object_t type, + void *object) { struct prefix_list *plist; - if (type != RMAP_OSPF6) - return RMAP_NOMATCH; - plist = prefix_list_lookup(AFI_IP6, (char *)rule); if (plist == NULL) return RMAP_NOMATCH; @@ -1440,18 +1436,16 @@ static const struct route_map_rule_cmd zero. */ static enum route_map_cmd_result_t ospf6_routemap_rule_match_interface(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { struct interface *ifp; struct ospf6_external_info *ei; - if (type == RMAP_OSPF6) { - ei = ((struct ospf6_route *)object)->route_option; - ifp = if_lookup_by_name_all_vrf((char *)rule); + ei = ((struct ospf6_route *)object)->route_option; + ifp = if_lookup_by_name_all_vrf((char *)rule); - if (ifp != NULL && ei->ifindex == ifp->ifindex) - return RMAP_MATCH; - } + if (ifp != NULL && ei->ifindex == ifp->ifindex) + return RMAP_MATCH; return RMAP_NOMATCH; } @@ -1480,14 +1474,13 @@ static const struct route_map_rule_cmd /* Match function for matching route tags */ static enum route_map_cmd_result_t -ospf6_routemap_rule_match_tag(void *rule, const struct prefix *p, - route_map_object_t type, void *object) +ospf6_routemap_rule_match_tag(void *rule, const struct prefix *p, void *object) { route_tag_t *tag = rule; struct ospf6_route *route = object; struct ospf6_external_info *info = route->route_option; - if (type == RMAP_OSPF6 && info->tag == *tag) + if (info->tag == *tag) return RMAP_MATCH; return RMAP_NOMATCH; @@ -1503,14 +1496,11 @@ static const struct route_map_rule_cmd static enum route_map_cmd_result_t ospf6_routemap_rule_set_metric_type(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { char *metric_type = rule; struct ospf6_route *route = object; - if (type != RMAP_OSPF6) - return RMAP_OKAY; - if (strcmp(metric_type, "type-2") == 0) route->path.metric_type = 2; else @@ -1541,14 +1531,11 @@ static const struct route_map_rule_cmd static enum route_map_cmd_result_t ospf6_routemap_rule_set_metric(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { char *metric = rule; struct ospf6_route *route = object; - if (type != RMAP_OSPF6) - return RMAP_OKAY; - route->path.cost = atoi(metric); return RMAP_OKAY; } @@ -1578,15 +1565,12 @@ static const struct route_map_rule_cmd static enum route_map_cmd_result_t ospf6_routemap_rule_set_forwarding(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { char *forwarding = rule; struct ospf6_route *route = object; struct ospf6_external_info *info = route->route_option; - if (type != RMAP_OSPF6) - return RMAP_OKAY; - if (inet_pton(AF_INET6, forwarding, &info->forwarding) != 1) { memset(&info->forwarding, 0, sizeof(struct in6_addr)); return RMAP_ERROR; @@ -1617,16 +1601,12 @@ static const struct route_map_rule_cmd }; static enum route_map_cmd_result_t -ospf6_routemap_rule_set_tag(void *rule, const struct prefix *p, - route_map_object_t type, void *object) +ospf6_routemap_rule_set_tag(void *rule, const struct prefix *p, void *object) { route_tag_t *tag = rule; struct ospf6_route *route = object; struct ospf6_external_info *info = route->route_option; - if (type != RMAP_OSPF6) - return RMAP_OKAY; - info->tag = *tag; return RMAP_OKAY; } diff --git a/ospf6d/ospf6_bfd.c b/ospf6d/ospf6_bfd.c index 4e50ab5244..523ed7f181 100644 --- a/ospf6d/ospf6_bfd.c +++ b/ospf6d/ospf6_bfd.c @@ -55,12 +55,13 @@ void ospf6_bfd_info_free(void **bfd_info) /* * ospf6_bfd_show_info - Show BFD info structure */ -void ospf6_bfd_show_info(struct vty *vty, void *bfd_info, int param_only) +void ospf6_bfd_show_info(struct vty *vty, void *bfd_info, int param_only, + json_object *json_obj, bool use_json) { if (param_only) bfd_show_param(vty, bfd_info, 1, 0, 0, NULL); else - bfd_show_info(vty, bfd_info, 0, 1, 0, NULL); + bfd_show_info(vty, bfd_info, 0, 1, use_json, json_obj); } /* diff --git a/ospf6d/ospf6_bfd.h b/ospf6d/ospf6_bfd.h index 19dff1ff7c..b4e798e911 100644 --- a/ospf6d/ospf6_bfd.h +++ b/ospf6d/ospf6_bfd.h @@ -19,7 +19,7 @@ * with this program; see the file COPYING; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - +#include "lib/json.h" #ifndef OSPF6_BFD_H #define OSPF6_BFD_H @@ -35,8 +35,8 @@ extern void ospf6_bfd_info_nbr_create(struct ospf6_interface *oi, extern void ospf6_bfd_info_free(void **bfd_info); -extern void ospf6_bfd_show_info(struct vty *vty, void *bfd_info, - int param_only); +extern void ospf6_bfd_show_info(struct vty *vty, void *bfd_info, int param_only, + json_object *json_obj, bool use_json); extern void ospf6_bfd_reg_dereg_nbr(struct ospf6_neighbor *on, int command); #endif /* OSPF6_BFD_H */ diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 75917b9d85..2d1b5e7b5a 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -996,7 +996,7 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp) (oi->thread_send_lsack ? "on" : "off")); for (ALL_LSDB(oi->lsack_list, lsa, lsanext)) vty_out(vty, " %s\n", lsa->name); - ospf6_bfd_show_info(vty, oi->bfd_info, 1); + ospf6_bfd_show_info(vty, oi->bfd_info, 1, NULL, false); return 0; } diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index 9f13ecffa1..c1905e8c1e 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -44,6 +44,7 @@ #include "ospf6_lsa.h" #include "ospf6_spf.h" #include "ospf6_zebra.h" +#include "lib/json.h" DEFINE_HOOK(ospf6_neighbor_change, (struct ospf6_neighbor * on, int state, int next_state), @@ -595,7 +596,8 @@ int inactivity_timer(struct thread *thread) /* vty functions */ /* show neighbor structure */ -static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on) +static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on, + json_object *json_array, bool use_json) { char router_id[16]; char duration[64]; @@ -603,6 +605,7 @@ static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on) char nstate[16]; char deadtime[64]; long h, m, s; + json_object *json_route; /* Router-ID (Name) */ inet_ntop(AF_INET, &on->router_id, router_id, sizeof(router_id)); @@ -641,23 +644,43 @@ static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on) /* vty_out (vty, "%-15s %3d %11s %6s/%-12s %11s %s[%s]\n", - "Neighbor ID", "Pri", "DeadTime", "State", "", "Duration", - "I/F", "State"); + "Neighbor ID", "Pri", "DeadTime", "State", "IfState", + "Duration", "I/F", "State"); */ - - vty_out(vty, "%-15s %3d %11s %8s/%-12s %11s %s[%s]\n", router_id, - on->priority, deadtime, ospf6_neighbor_state_str[on->state], - nstate, duration, on->ospf6_if->interface->name, - ospf6_interface_state_str[on->ospf6_if->state]); + if (use_json) { + json_route = json_object_new_object(); + + json_object_string_add(json_route, "neighborId", router_id); + json_object_int_add(json_route, "priority", on->priority); + json_object_string_add(json_route, "deadTime", deadtime); + json_object_string_add(json_route, "state", + ospf6_neighbor_state_str[on->state]); + json_object_string_add(json_route, "ifState", nstate); + json_object_string_add(json_route, "duration", duration); + json_object_string_add(json_route, "interfaceName", + on->ospf6_if->interface->name); + json_object_string_add( + json_route, "interfaceState", + ospf6_interface_state_str[on->ospf6_if->state]); + + json_object_array_add(json_array, json_route); + } else + vty_out(vty, "%-15s %3d %11s %8s/%-12s %11s %s[%s]\n", + router_id, on->priority, deadtime, + ospf6_neighbor_state_str[on->state], nstate, duration, + on->ospf6_if->interface->name, + ospf6_interface_state_str[on->ospf6_if->state]); } static void ospf6_neighbor_show_drchoice(struct vty *vty, - struct ospf6_neighbor *on) + struct ospf6_neighbor *on, + json_object *json_array, bool use_json) { char router_id[16]; char drouter[16], bdrouter[16]; char duration[64]; struct timeval now, res; + json_object *json_route; /* vty_out (vty, "%-15s %6s/%-11s %-15s %-15s %s[%s]\n", @@ -673,19 +696,39 @@ static void ospf6_neighbor_show_drchoice(struct vty *vty, timersub(&now, &on->last_changed, &res); timerstring(&res, duration, sizeof(duration)); - vty_out(vty, "%-15s %8s/%-11s %-15s %-15s %s[%s]\n", router_id, - ospf6_neighbor_state_str[on->state], duration, drouter, - bdrouter, on->ospf6_if->interface->name, - ospf6_interface_state_str[on->ospf6_if->state]); + if (use_json) { + json_route = json_object_new_object(); + json_object_string_add(json_route, "routerId", router_id); + json_object_string_add(json_route, "state", + ospf6_neighbor_state_str[on->state]); + json_object_string_add(json_route, "duration", duration); + json_object_string_add(json_route, "dRouter", drouter); + json_object_string_add(json_route, "bdRouter", bdrouter); + json_object_string_add(json_route, "interfaceName", + on->ospf6_if->interface->name); + json_object_string_add( + json_route, "interfaceState", + ospf6_interface_state_str[on->ospf6_if->state]); + + json_object_array_add(json_array, json_route); + } else + vty_out(vty, "%-15s %8s/%-11s %-15s %-15s %s[%s]\n", router_id, + ospf6_neighbor_state_str[on->state], duration, drouter, + bdrouter, on->ospf6_if->interface->name, + ospf6_interface_state_str[on->ospf6_if->state]); } static void ospf6_neighbor_show_detail(struct vty *vty, - struct ospf6_neighbor *on) + struct ospf6_neighbor *on, + json_object *json, bool use_json) { char drouter[16], bdrouter[16]; char linklocal_addr[64], duration[32]; struct timeval now, res; struct ospf6_lsa *lsa, *lsanext; + json_object *json_neighbor; + json_object *json_array; + char db_desc_str[20]; inet_ntop(AF_INET6, &on->linklocal_addr, linklocal_addr, sizeof(linklocal_addr)); @@ -696,149 +739,333 @@ static void ospf6_neighbor_show_detail(struct vty *vty, timersub(&now, &on->last_changed, &res); timerstring(&res, duration, sizeof(duration)); - vty_out(vty, " Neighbor %s\n", on->name); - vty_out(vty, " Area %s via interface %s (ifindex %d)\n", - on->ospf6_if->area->name, on->ospf6_if->interface->name, - on->ospf6_if->interface->ifindex); - vty_out(vty, " His IfIndex: %d Link-local address: %s\n", - on->ifindex, linklocal_addr); - vty_out(vty, " State %s for a duration of %s\n", - ospf6_neighbor_state_str[on->state], duration); - vty_out(vty, " His choice of DR/BDR %s/%s, Priority %d\n", drouter, - bdrouter, on->priority); - vty_out(vty, " DbDesc status: %s%s%s SeqNum: %#lx\n", - (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT) ? "Initial " - : ""), - (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT) ? "More " : ""), - (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT) ? "Master" - : "Slave"), - (unsigned long)ntohl(on->dbdesc_seqnum)); - - vty_out(vty, " Summary-List: %d LSAs\n", on->summary_list->count); - for (ALL_LSDB(on->summary_list, lsa, lsanext)) - vty_out(vty, " %s\n", lsa->name); - - vty_out(vty, " Request-List: %d LSAs\n", on->request_list->count); - for (ALL_LSDB(on->request_list, lsa, lsanext)) - vty_out(vty, " %s\n", lsa->name); - - vty_out(vty, " Retrans-List: %d LSAs\n", on->retrans_list->count); - for (ALL_LSDB(on->retrans_list, lsa, lsanext)) - vty_out(vty, " %s\n", lsa->name); - - timerclear(&res); - if (on->thread_send_dbdesc) - timersub(&on->thread_send_dbdesc->u.sands, &now, &res); - timerstring(&res, duration, sizeof(duration)); - vty_out(vty, " %d Pending LSAs for DbDesc in Time %s [thread %s]\n", - on->dbdesc_list->count, duration, - (on->thread_send_dbdesc ? "on" : "off")); - for (ALL_LSDB(on->dbdesc_list, lsa, lsanext)) - vty_out(vty, " %s\n", lsa->name); - - timerclear(&res); - if (on->thread_send_lsreq) - timersub(&on->thread_send_lsreq->u.sands, &now, &res); - timerstring(&res, duration, sizeof(duration)); - vty_out(vty, " %d Pending LSAs for LSReq in Time %s [thread %s]\n", - on->request_list->count, duration, - (on->thread_send_lsreq ? "on" : "off")); - for (ALL_LSDB(on->request_list, lsa, lsanext)) - vty_out(vty, " %s\n", lsa->name); - - timerclear(&res); - if (on->thread_send_lsupdate) - timersub(&on->thread_send_lsupdate->u.sands, &now, &res); - timerstring(&res, duration, sizeof(duration)); - vty_out(vty, - " %d Pending LSAs for LSUpdate in Time %s [thread %s]\n", - on->lsupdate_list->count, duration, - (on->thread_send_lsupdate ? "on" : "off")); - for (ALL_LSDB(on->lsupdate_list, lsa, lsanext)) - vty_out(vty, " %s\n", lsa->name); - - timerclear(&res); - if (on->thread_send_lsack) - timersub(&on->thread_send_lsack->u.sands, &now, &res); - timerstring(&res, duration, sizeof(duration)); - vty_out(vty, " %d Pending LSAs for LSAck in Time %s [thread %s]\n", - on->lsack_list->count, duration, - (on->thread_send_lsack ? "on" : "off")); - for (ALL_LSDB(on->lsack_list, lsa, lsanext)) - vty_out(vty, " %s\n", lsa->name); - - ospf6_bfd_show_info(vty, on->bfd_info, 0); + if (use_json) { + json_neighbor = json_object_new_object(); + json_object_string_add(json_neighbor, "area", + on->ospf6_if->area->name); + json_object_string_add(json_neighbor, "interface", + on->ospf6_if->interface->name); + json_object_int_add(json_neighbor, "interfaceIndex", + on->ospf6_if->interface->ifindex); + json_object_int_add(json_neighbor, "neighborInterfaceIndex", + on->ifindex); + json_object_string_add(json_neighbor, "linkLocalAddress", + linklocal_addr); + json_object_string_add(json_neighbor, "neighborState", + ospf6_neighbor_state_str[on->state]); + json_object_string_add(json_neighbor, "neighborStateDuration", + duration); + json_object_string_add(json_neighbor, "neighborDRouter", + drouter); + json_object_string_add(json_neighbor, "neighborBdRouter", + bdrouter); + snprintf(db_desc_str, sizeof(db_desc_str), "%s%s%s", + (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT) + ? "Initial " + : ""), + (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT) + ? "More" + : ""), + (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT) + ? "Master" + : "Slave")); + json_object_string_add(json_neighbor, "dbDescStatus", + db_desc_str); + + json_object_int_add(json_neighbor, "dbDescSeqNumber", + (unsigned long)ntohl(on->dbdesc_seqnum)); + + json_array = json_object_new_array(); + json_object_int_add(json_neighbor, "summaryListCount", + on->summary_list->count); + for (ALL_LSDB(on->summary_list, lsa, lsanext)) + json_object_array_add( + json_array, json_object_new_string(lsa->name)); + json_object_object_add(json_neighbor, "summaryListLsa", + json_array); + + json_array = json_object_new_array(); + json_object_int_add(json_neighbor, "requestListCount", + on->request_list->count); + for (ALL_LSDB(on->request_list, lsa, lsanext)) + json_object_array_add( + json_array, json_object_new_string(lsa->name)); + json_object_object_add(json_neighbor, "requestListLsa", + json_array); + + json_array = json_object_new_array(); + json_object_int_add(json_neighbor, "reTransListCount", + on->retrans_list->count); + for (ALL_LSDB(on->retrans_list, lsa, lsanext)) + json_object_array_add( + json_array, json_object_new_string(lsa->name)); + json_object_object_add(json_neighbor, "reTransListLsa", + json_array); + + + timerclear(&res); + if (on->thread_send_dbdesc) + timersub(&on->thread_send_dbdesc->u.sands, &now, &res); + timerstring(&res, duration, sizeof(duration)); + json_object_int_add(json_neighbor, "pendingLsaDbDescCount", + on->dbdesc_list->count); + json_object_string_add(json_neighbor, "pendingLsaDbDescTime", + duration); + json_object_string_add(json_neighbor, "dbDescSendThread", + (on->thread_send_dbdesc ? "on" : "off")); + json_array = json_object_new_array(); + for (ALL_LSDB(on->dbdesc_list, lsa, lsanext)) + json_object_array_add( + json_array, json_object_new_string(lsa->name)); + json_object_object_add(json_neighbor, "pendingLsaDbDesc", + json_array); + + timerclear(&res); + if (on->thread_send_lsreq) + timersub(&on->thread_send_lsreq->u.sands, &now, &res); + timerstring(&res, duration, sizeof(duration)); + json_object_int_add(json_neighbor, "pendingLsaLsReqCount", + on->request_list->count); + json_object_string_add(json_neighbor, "pendingLsaLsReqTime", + duration); + json_object_string_add(json_neighbor, "lsReqSendThread", + (on->thread_send_lsreq ? "on" : "off")); + json_array = json_object_new_array(); + for (ALL_LSDB(on->request_list, lsa, lsanext)) + json_object_array_add( + json_array, json_object_new_string(lsa->name)); + json_object_object_add(json_neighbor, "pendingLsaLsReq", + json_array); + + + timerclear(&res); + if (on->thread_send_lsupdate) + timersub(&on->thread_send_lsupdate->u.sands, &now, + &res); + timerstring(&res, duration, sizeof(duration)); + json_object_int_add(json_neighbor, "pendingLsaLsUpdateCount", + on->lsupdate_list->count); + json_object_string_add(json_neighbor, "pendingLsaLsUpdateTime", + duration); + json_object_string_add( + json_neighbor, "lsUpdateSendThread", + (on->thread_send_lsupdate ? "on" : "off")); + json_array = json_object_new_array(); + for (ALL_LSDB(on->lsupdate_list, lsa, lsanext)) + json_object_array_add( + json_array, json_object_new_string(lsa->name)); + json_object_object_add(json_neighbor, "pendingLsaLsUpdate", + json_array); + + timerclear(&res); + if (on->thread_send_lsack) + timersub(&on->thread_send_lsack->u.sands, &now, &res); + timerstring(&res, duration, sizeof(duration)); + json_object_int_add(json_neighbor, "pendingLsaLsAckCount", + on->lsack_list->count); + json_object_string_add(json_neighbor, "pendingLsaLsAckTime", + duration); + json_object_string_add(json_neighbor, "lsAckSendThread", + (on->thread_send_lsack ? "on" : "off")); + json_array = json_object_new_array(); + for (ALL_LSDB(on->lsack_list, lsa, lsanext)) + json_object_array_add( + json_array, json_object_new_string(lsa->name)); + json_object_object_add(json_neighbor, "pendingLsaLsAck", + json_array); + + ospf6_bfd_show_info(vty, on->bfd_info, 0, json_neighbor, + use_json); + + json_object_object_add(json, on->name, json_neighbor); + + + } else { + vty_out(vty, " Neighbor %s\n", on->name); + vty_out(vty, " Area %s via interface %s (ifindex %d)\n", + on->ospf6_if->area->name, on->ospf6_if->interface->name, + on->ospf6_if->interface->ifindex); + vty_out(vty, " His IfIndex: %d Link-local address: %s\n", + on->ifindex, linklocal_addr); + vty_out(vty, " State %s for a duration of %s\n", + ospf6_neighbor_state_str[on->state], duration); + vty_out(vty, " His choice of DR/BDR %s/%s, Priority %d\n", + drouter, bdrouter, on->priority); + vty_out(vty, " DbDesc status: %s%s%s SeqNum: %#lx\n", + (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_IBIT) + ? "Initial " + : ""), + (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MBIT) + ? "More " + : ""), + (CHECK_FLAG(on->dbdesc_bits, OSPF6_DBDESC_MSBIT) + ? "Master" + : "Slave"), + (unsigned long)ntohl(on->dbdesc_seqnum)); + + vty_out(vty, " Summary-List: %d LSAs\n", + on->summary_list->count); + for (ALL_LSDB(on->summary_list, lsa, lsanext)) + vty_out(vty, " %s\n", lsa->name); + + vty_out(vty, " Request-List: %d LSAs\n", + on->request_list->count); + for (ALL_LSDB(on->request_list, lsa, lsanext)) + vty_out(vty, " %s\n", lsa->name); + + vty_out(vty, " Retrans-List: %d LSAs\n", + on->retrans_list->count); + for (ALL_LSDB(on->retrans_list, lsa, lsanext)) + vty_out(vty, " %s\n", lsa->name); + + timerclear(&res); + if (on->thread_send_dbdesc) + timersub(&on->thread_send_dbdesc->u.sands, &now, &res); + timerstring(&res, duration, sizeof(duration)); + vty_out(vty, + " %d Pending LSAs for DbDesc in Time %s [thread %s]\n", + on->dbdesc_list->count, duration, + (on->thread_send_dbdesc ? "on" : "off")); + for (ALL_LSDB(on->dbdesc_list, lsa, lsanext)) + vty_out(vty, " %s\n", lsa->name); + + timerclear(&res); + if (on->thread_send_lsreq) + timersub(&on->thread_send_lsreq->u.sands, &now, &res); + timerstring(&res, duration, sizeof(duration)); + vty_out(vty, + " %d Pending LSAs for LSReq in Time %s [thread %s]\n", + on->request_list->count, duration, + (on->thread_send_lsreq ? "on" : "off")); + for (ALL_LSDB(on->request_list, lsa, lsanext)) + vty_out(vty, " %s\n", lsa->name); + + timerclear(&res); + if (on->thread_send_lsupdate) + timersub(&on->thread_send_lsupdate->u.sands, &now, + &res); + timerstring(&res, duration, sizeof(duration)); + vty_out(vty, + " %d Pending LSAs for LSUpdate in Time %s [thread %s]\n", + on->lsupdate_list->count, duration, + (on->thread_send_lsupdate ? "on" : "off")); + for (ALL_LSDB(on->lsupdate_list, lsa, lsanext)) + vty_out(vty, " %s\n", lsa->name); + + timerclear(&res); + if (on->thread_send_lsack) + timersub(&on->thread_send_lsack->u.sands, &now, &res); + timerstring(&res, duration, sizeof(duration)); + vty_out(vty, + " %d Pending LSAs for LSAck in Time %s [thread %s]\n", + on->lsack_list->count, duration, + (on->thread_send_lsack ? "on" : "off")); + for (ALL_LSDB(on->lsack_list, lsa, lsanext)) + vty_out(vty, " %s\n", lsa->name); + + ospf6_bfd_show_info(vty, on->bfd_info, 0, NULL, use_json); + } } DEFUN (show_ipv6_ospf6_neighbor, show_ipv6_ospf6_neighbor_cmd, - "show ipv6 ospf6 neighbor [<detail|drchoice>]", + "show ipv6 ospf6 neighbor [<detail|drchoice>] [json]", SHOW_STR IP6_STR OSPF6_STR "Neighbor list\n" "Display details\n" - "Display DR choices\n") + "Display DR choices\n" + JSON_STR) { int idx_type = 4; struct ospf6_neighbor *on; struct ospf6_interface *oi; struct ospf6_area *oa; struct listnode *i, *j, *k; - void (*showfunc)(struct vty *, struct ospf6_neighbor *); struct ospf6 *ospf6; + json_object *json = NULL; + json_object *json_array = NULL; + bool uj = use_json(argc, argv); + void (*showfunc)(struct vty *, struct ospf6_neighbor *, + json_object *json, bool use_json); ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); OSPF6_CMD_CHECK_RUNNING(ospf6); showfunc = ospf6_neighbor_show; - if (argc == 5) { + if ((uj && argc == 6) || (!uj && argc == 5)) { if (!strncmp(argv[idx_type]->arg, "de", 2)) showfunc = ospf6_neighbor_show_detail; else if (!strncmp(argv[idx_type]->arg, "dr", 2)) showfunc = ospf6_neighbor_show_drchoice; } - if (showfunc == ospf6_neighbor_show) - vty_out(vty, "%-15s %3s %11s %8s/%-12s %11s %s[%s]\n", - "Neighbor ID", "Pri", "DeadTime", "State", "IfState", - "Duration", "I/F", "State"); - else if (showfunc == ospf6_neighbor_show_drchoice) - vty_out(vty, "%-15s %8s/%-11s %-15s %-15s %s[%s]\n", "RouterID", - "State", "Duration", "DR", "BDR", "I/F", "State"); + if (uj) { + json = json_object_new_object(); + json_array = json_object_new_array(); + } else { + if (showfunc == ospf6_neighbor_show) + vty_out(vty, "%-15s %3s %11s %8s/%-12s %11s %s[%s]\n", + "Neighbor ID", "Pri", "DeadTime", "State", + "IfState", "Duration", "I/F", "State"); + else if (showfunc == ospf6_neighbor_show_drchoice) + vty_out(vty, "%-15s %8s/%-11s %-15s %-15s %s[%s]\n", + "RouterID", "State", "Duration", "DR", "BDR", + "I/F", "State"); + } for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) - for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on)) - (*showfunc)(vty, on); - + for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on)) { + if (showfunc == ospf6_neighbor_show_detail) + (*showfunc)(vty, on, json, uj); + else + (*showfunc)(vty, on, json_array, uj); + } + + if (uj) { + if (showfunc != ospf6_neighbor_show_detail) + json_object_object_add(json, "neighbors", json_array); + else + json_object_free(json_array); + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } return CMD_SUCCESS; } DEFUN (show_ipv6_ospf6_neighbor_one, show_ipv6_ospf6_neighbor_one_cmd, - "show ipv6 ospf6 neighbor A.B.C.D", + "show ipv6 ospf6 neighbor A.B.C.D [json]", SHOW_STR IP6_STR OSPF6_STR "Neighbor list\n" "Specify Router-ID as IPv4 address notation\n" - ) + JSON_STR) { int idx_ipv4 = 4; struct ospf6_neighbor *on; struct ospf6_interface *oi; struct ospf6_area *oa; struct listnode *i, *j, *k; - void (*showfunc)(struct vty *, struct ospf6_neighbor *); + void (*showfunc)(struct vty *, struct ospf6_neighbor *, + json_object *json, bool use_json); uint32_t router_id; struct ospf6 *ospf6; + json_object *json = NULL; + bool uj = use_json(argc, argv); ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME); OSPF6_CMD_CHECK_RUNNING(ospf6); showfunc = ospf6_neighbor_show_detail; + if (uj) + json = json_object_new_object(); if ((inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id)) != 1) { vty_out(vty, "Router-ID is not parsable: %s\n", @@ -849,8 +1076,15 @@ DEFUN (show_ipv6_ospf6_neighbor_one, for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) for (ALL_LIST_ELEMENTS_RO(oa->if_list, j, oi)) for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, k, on)) - (*showfunc)(vty, on); + (*showfunc)(vty, on, json, uj); + + if (uj) { + vty_out(vty, "%s\n", + json_object_to_json_string_ext( + json, JSON_C_TO_STRING_PRETTY)); + json_object_free(json); + } return CMD_SUCCESS; } diff --git a/ospf6d/ospf6_neighbor.h b/ospf6d/ospf6_neighbor.h index 1a45a1966a..94300ff2ba 100644 --- a/ospf6d/ospf6_neighbor.h +++ b/ospf6d/ospf6_neighbor.h @@ -64,7 +64,7 @@ struct ospf6_neighbor { /* Options field (Capability) */ char options[3]; - /* IPaddr of I/F on our side link */ + /* IPaddr of I/F on neighbour's link */ struct in6_addr linklocal_addr; /* For Database Exchange */ diff --git a/ospfd/ospf_gr_helper.c b/ospfd/ospf_gr_helper.c index 9c029a49ba..a86e1b8401 100644 --- a/ospfd/ospf_gr_helper.c +++ b/ospfd/ospf_gr_helper.c @@ -251,7 +251,7 @@ static int ospf_extract_grace_lsa_fields(struct ospf_lsa *lsa, /* Check TLV len against overall LSA */ if (sum + TLV_SIZE(tlvh) > length) { if (IS_DEBUG_OSPF_GR_HELPER) - zlog_debug("%s: Malformed packet: Invalid TLV len:%zu", + zlog_debug("%s: Malformed packet: Invalid TLV len:%u", __func__, TLV_SIZE(tlvh)); return OSPF_GR_FAILURE; } @@ -260,7 +260,7 @@ static int ospf_extract_grace_lsa_fields(struct ospf_lsa *lsa, case GRACE_PERIOD_TYPE: if (TLV_SIZE(tlvh) < sizeof(struct grace_tlv_graceperiod)) { - zlog_debug("%s: Malformed packet: Invalid grace TLV len:%zu", + zlog_debug("%s: Malformed packet: Invalid grace TLV len:%u", __func__, TLV_SIZE(tlvh)); return OSPF_GR_FAILURE; } @@ -277,7 +277,7 @@ static int ospf_extract_grace_lsa_fields(struct ospf_lsa *lsa, case RESTART_REASON_TYPE: if (TLV_SIZE(tlvh) < sizeof(struct grace_tlv_restart_reason)) { - zlog_debug("%s: Malformed packet: Invalid reason TLV len:%zu", + zlog_debug("%s: Malformed packet: Invalid reason TLV len:%u", __func__, TLV_SIZE(tlvh)); return OSPF_GR_FAILURE; } @@ -292,7 +292,7 @@ static int ospf_extract_grace_lsa_fields(struct ospf_lsa *lsa, case RESTARTER_IP_ADDR_TYPE: if (TLV_SIZE(tlvh) < sizeof(struct grace_tlv_restart_addr)) { - zlog_debug("%s: Malformed packet: Invalid addr TLV len:%zu", + zlog_debug("%s: Malformed packet: Invalid addr TLV len:%u", __func__, TLV_SIZE(tlvh)); return OSPF_GR_FAILURE; } @@ -1018,7 +1018,7 @@ static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa) tlvh = TLV_HDR_NEXT(tlvh)) { /* Check TLV len */ if (sum + TLV_SIZE(tlvh) > length) { - vty_out(vty, "%% Invalid TLV length: %zu\n", + vty_out(vty, "%% Invalid TLV length: %u\n", TLV_SIZE(tlvh)); return; } @@ -1028,7 +1028,7 @@ static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa) if (TLV_SIZE(tlvh) < sizeof(struct grace_tlv_graceperiod)) { vty_out(vty, - "%% Invalid grace TLV length %zu\n", + "%% Invalid grace TLV length %u\n", TLV_SIZE(tlvh)); return; } @@ -1043,7 +1043,7 @@ static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa) if (TLV_SIZE(tlvh) < sizeof(struct grace_tlv_restart_reason)) { vty_out(vty, - "%% Invalid reason TLV length %zu\n", + "%% Invalid reason TLV length %u\n", TLV_SIZE(tlvh)); return; } @@ -1058,7 +1058,7 @@ static void show_ospf_grace_lsa_info(struct vty *vty, struct ospf_lsa *lsa) if (TLV_SIZE(tlvh) < sizeof(struct grace_tlv_restart_addr)) { vty_out(vty, - "%% Invalid addr TLV length %zu\n", + "%% Invalid addr TLV length %u\n", TLV_SIZE(tlvh)); return; } diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index eb0c4a949a..3939b5479f 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -126,6 +126,8 @@ void ospf_opaque_term(void) void ospf_opaque_finish(void) { + ospf_mpls_te_finish(); + ospf_router_info_finish(); ospf_ext_finish(); diff --git a/ospfd/ospf_opaque.h b/ospfd/ospf_opaque.h index f02f34c9af..c63b8ebdaf 100644 --- a/ospfd/ospf_opaque.h +++ b/ospfd/ospf_opaque.h @@ -94,7 +94,7 @@ struct tlv_header { #define TLV_BODY_SIZE(tlvh) (ROUNDUP(ntohs((tlvh)->length), sizeof(uint32_t))) -#define TLV_SIZE(tlvh) (TLV_HDR_SIZE + TLV_BODY_SIZE(tlvh)) +#define TLV_SIZE(tlvh) (uint32_t)(TLV_HDR_SIZE + TLV_BODY_SIZE(tlvh)) #define TLV_HDR_TOP(lsah) \ (struct tlv_header *)((char *)(lsah) + OSPF_LSA_HEADER_SIZE) diff --git a/ospfd/ospf_routemap.c b/ospfd/ospf_routemap.c index c89fd3597f..f9e11541fc 100644 --- a/ospfd/ospf_routemap.c +++ b/ospfd/ospf_routemap.c @@ -127,27 +127,22 @@ static void ospf_route_map_event(const char *name) /* `match ip netxthop ' */ /* Match function return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_ip_nexthop(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_nexthop(void *rule, const struct prefix *prefix, void *object) { struct access_list *alist; struct external_info *ei = object; struct prefix_ipv4 p; - if (type == RMAP_OSPF) { - p.family = AF_INET; - p.prefix = ei->nexthop; - p.prefixlen = IPV4_MAX_BITLEN; + p.family = AF_INET; + p.prefix = ei->nexthop; + p.prefixlen = IPV4_MAX_BITLEN; - alist = access_list_lookup(AFI_IP, (char *)rule); - if (alist == NULL) - return RMAP_NOMATCH; + alist = access_list_lookup(AFI_IP, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; - return (access_list_apply(alist, &p) == FILTER_DENY - ? RMAP_NOMATCH - : RMAP_MATCH); - } - return RMAP_NOMATCH; + return (access_list_apply(alist, &p) == FILTER_DENY ? RMAP_NOMATCH + : RMAP_MATCH); } /* Route map `ip next-hop' match statement. `arg' should be @@ -175,26 +170,22 @@ static const struct route_map_rule_cmd route_match_ip_nexthop_cmd = { static enum route_map_cmd_result_t route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { struct prefix_list *plist; struct external_info *ei = object; struct prefix_ipv4 p; - if (type == RMAP_OSPF) { - p.family = AF_INET; - p.prefix = ei->nexthop; - p.prefixlen = IPV4_MAX_BITLEN; + p.family = AF_INET; + p.prefix = ei->nexthop; + p.prefixlen = IPV4_MAX_BITLEN; - plist = prefix_list_lookup(AFI_IP, (char *)rule); - if (plist == NULL) - return RMAP_NOMATCH; + plist = prefix_list_lookup(AFI_IP, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; - return (prefix_list_apply(plist, &p) == PREFIX_DENY - ? RMAP_NOMATCH - : RMAP_MATCH); - } - return RMAP_NOMATCH; + return (prefix_list_apply(plist, &p) == PREFIX_DENY ? RMAP_NOMATCH + : RMAP_MATCH); } static void *route_match_ip_next_hop_prefix_list_compile(const char *arg) @@ -219,11 +210,11 @@ static const struct route_map_rule_cmd static enum route_map_cmd_result_t route_match_ip_next_hop_type(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { struct external_info *ei = object; - if (type == RMAP_OSPF && prefix->family == AF_INET) { + if (prefix->family == AF_INET) { ei = (struct external_info *)object; if (!ei) return RMAP_NOMATCH; @@ -256,22 +247,17 @@ static const struct route_map_rule_cmd /* Match function should return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_ip_address(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_address(void *rule, const struct prefix *prefix, void *object) { struct access_list *alist; /* struct prefix_ipv4 match; */ - if (type == RMAP_OSPF) { - alist = access_list_lookup(AFI_IP, (char *)rule); - if (alist == NULL) - return RMAP_NOMATCH; + alist = access_list_lookup(AFI_IP, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; - return (access_list_apply(alist, prefix) == FILTER_DENY - ? RMAP_NOMATCH - : RMAP_MATCH); - } - return RMAP_NOMATCH; + return (access_list_apply(alist, prefix) == FILTER_DENY ? RMAP_NOMATCH + : RMAP_MATCH); } /* Route map `ip address' match statement. `arg' should be @@ -298,20 +284,16 @@ static const struct route_map_rule_cmd route_match_ip_address_cmd = { /* `match ip address prefix-list PREFIX_LIST' */ static enum route_map_cmd_result_t route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { struct prefix_list *plist; - if (type == RMAP_OSPF) { - plist = prefix_list_lookup(AFI_IP, (char *)rule); - if (plist == NULL) - return RMAP_NOMATCH; + plist = prefix_list_lookup(AFI_IP, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; - return (prefix_list_apply(plist, prefix) == PREFIX_DENY - ? RMAP_NOMATCH - : RMAP_MATCH); - } - return RMAP_NOMATCH; + return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH + : RMAP_MATCH); } static void *route_match_ip_address_prefix_list_compile(const char *arg) @@ -336,22 +318,18 @@ static const struct route_map_rule_cmd /* Match function should return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_interface(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_interface(void *rule, const struct prefix *prefix, void *object) { struct interface *ifp; struct external_info *ei; - if (type == RMAP_OSPF) { - ei = object; - ifp = if_lookup_by_name_all_vrf((char *)rule); + ei = object; + ifp = if_lookup_by_name_all_vrf((char *)rule); - if (ifp == NULL || ifp->ifindex != ei->ifindex) - return RMAP_NOMATCH; + if (ifp == NULL || ifp->ifindex != ei->ifindex) + return RMAP_NOMATCH; - return RMAP_MATCH; - } - return RMAP_NOMATCH; + return RMAP_MATCH; } /* Route map `interface' match statement. `arg' should be @@ -377,20 +355,15 @@ static const struct route_map_rule_cmd route_match_interface_cmd = { /* Match function return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_tag(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_tag(void *rule, const struct prefix *prefix, void *object) { route_tag_t *tag; struct external_info *ei; - if (type == RMAP_OSPF) { - tag = rule; - ei = object; + tag = rule; + ei = object; - return ((ei->tag == *tag) ? RMAP_MATCH : RMAP_NOMATCH); - } - - return RMAP_NOMATCH; + return ((ei->tag == *tag) ? RMAP_MATCH : RMAP_NOMATCH); } /* Route map commands for tag matching. */ @@ -410,33 +383,31 @@ struct ospf_metric { /* `set metric METRIC' */ /* Set metric to attribute. */ static enum route_map_cmd_result_t -route_set_metric(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_metric(void *rule, const struct prefix *prefix, void *object) { struct ospf_metric *metric; struct external_info *ei; - if (type == RMAP_OSPF) { - /* Fetch routemap's rule information. */ - metric = rule; - ei = object; + /* Fetch routemap's rule information. */ + metric = rule; + ei = object; - /* Set metric out value. */ - if (!metric->used) - return RMAP_OKAY; + /* Set metric out value. */ + if (!metric->used) + return RMAP_OKAY; - ei->route_map_set.metric = DEFAULT_DEFAULT_METRIC; + ei->route_map_set.metric = DEFAULT_DEFAULT_METRIC; - if (metric->type == metric_increment) - ei->route_map_set.metric += metric->metric; - else if (metric->type == metric_decrement) - ei->route_map_set.metric -= metric->metric; - else if (metric->type == metric_absolute) - ei->route_map_set.metric = metric->metric; + if (metric->type == metric_increment) + ei->route_map_set.metric += metric->metric; + else if (metric->type == metric_decrement) + ei->route_map_set.metric -= metric->metric; + else if (metric->type == metric_absolute) + ei->route_map_set.metric = metric->metric; + + if (ei->route_map_set.metric > OSPF_LS_INFINITY) + ei->route_map_set.metric = OSPF_LS_INFINITY; - if (ei->route_map_set.metric > OSPF_LS_INFINITY) - ei->route_map_set.metric = OSPF_LS_INFINITY; - } return RMAP_OKAY; } @@ -492,20 +463,18 @@ static const struct route_map_rule_cmd route_set_metric_cmd = { /* `set metric-type TYPE' */ /* Set metric-type to attribute. */ static enum route_map_cmd_result_t -route_set_metric_type(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_metric_type(void *rule, const struct prefix *prefix, void *object) { uint32_t *metric_type; struct external_info *ei; - if (type == RMAP_OSPF) { - /* Fetch routemap's rule information. */ - metric_type = rule; - ei = object; + /* Fetch routemap's rule information. */ + metric_type = rule; + ei = object; + + /* Set metric out value. */ + ei->route_map_set.metric_type = *metric_type; - /* Set metric out value. */ - ei->route_map_set.metric_type = *metric_type; - } return RMAP_OKAY; } @@ -543,19 +512,16 @@ static const struct route_map_rule_cmd route_set_metric_type_cmd = { }; static enum route_map_cmd_result_t -route_set_tag(void *rule, const struct prefix *prefix, route_map_object_t type, - void *object) +route_set_tag(void *rule, const struct prefix *prefix, void *object) { route_tag_t *tag; struct external_info *ei; - if (type == RMAP_OSPF) { - tag = rule; - ei = object; + tag = rule; + ei = object; - /* Set tag value */ - ei->tag = *tag; - } + /* Set tag value */ + ei->tag = *tag; return RMAP_OKAY; } diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c index e3c554c530..17ff9a1a46 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -187,6 +187,7 @@ void ospf_mpls_te_finish(void) // list_delete_all_node(OspfMplsTE.iflist); OspfMplsTE.enabled = false; + ospf_mpls_te_unregister(); OspfMplsTE.inter_as = Off; } @@ -2229,6 +2230,17 @@ DEFUN (no_ospf_mpls_te, if (CHECK_FLAG(lp->flags, LPFLG_LSA_ENGAGED)) ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA); + /* + * This resets the OspfMplsTE.inter_as to its initial state. + * This is to avoid having an inter-as value different from + * Off when mpls-te gets restarted (after being removed) + */ + if (OspfMplsTE.inter_as != Off) { + /* Deregister the Callbacks for Inter-AS support */ + ospf_mpls_te_unregister(); + OspfMplsTE.inter_as = Off; + } + return CMD_SUCCESS; } diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index fd965e8f21..d449f9d2fa 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -902,8 +902,7 @@ int ospf_external_info_apply_default_routemap(struct ospf *ospf, if (red && ROUTEMAP_NAME(red)) { route_map_result_t ret; - ret = route_map_apply(ROUTEMAP(red), (struct prefix *)p, - RMAP_OSPF, ei); + ret = route_map_apply(ROUTEMAP(red), (struct prefix *)p, ei); if (ret == RMAP_DENYMATCH) { ei->route_map_set = save_values; @@ -1056,8 +1055,7 @@ int ospf_redistribute_check(struct ospf *ospf, struct external_info *ei, if (red && ROUTEMAP_NAME(red)) { route_map_result_t ret; - ret = route_map_apply(ROUTEMAP(red), (struct prefix *)p, - RMAP_OSPF, ei); + ret = route_map_apply(ROUTEMAP(red), (struct prefix *)p, ei); if (ret == RMAP_DENYMATCH) { ei->route_map_set = save_values; diff --git a/pbrd/pbr_zebra.c b/pbrd/pbr_zebra.c index 32660b4dee..82a2d2feb5 100644 --- a/pbrd/pbr_zebra.c +++ b/pbrd/pbr_zebra.c @@ -167,7 +167,8 @@ static int route_notify_owner(ZAPI_CALLBACK_ARGS) enum zapi_route_notify_owner note; uint32_t table_id; - if (!zapi_route_notify_decode(zclient->ibuf, &p, &table_id, ¬e)) + if (!zapi_route_notify_decode(zclient->ibuf, &p, &table_id, ¬e, + NULL, NULL)) return -1; switch (note) { diff --git a/ripd/rip_routemap.c b/ripd/rip_routemap.c index 77c2db8ceb..061cefec30 100644 --- a/ripd/rip_routemap.c +++ b/ripd/rip_routemap.c @@ -43,27 +43,23 @@ struct rip_metric_modifier { /* `match metric METRIC' */ /* Match function return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_metric(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_metric(void *rule, const struct prefix *prefix, void *object) { uint32_t *metric; uint32_t check; struct rip_info *rinfo; - if (type == RMAP_RIP) { - metric = rule; - rinfo = object; - - /* If external metric is available, the route-map should - work on this one (for redistribute purpose) */ - check = (rinfo->external_metric) ? rinfo->external_metric - : rinfo->metric; - if (check == *metric) - return RMAP_MATCH; - else - return RMAP_NOMATCH; - } - return RMAP_NOMATCH; + metric = rule; + rinfo = object; + + /* If external metric is available, the route-map should + work on this one (for redistribute purpose) */ + check = (rinfo->external_metric) ? rinfo->external_metric + : rinfo->metric; + if (check == *metric) + return RMAP_MATCH; + else + return RMAP_NOMATCH; } /* Route map `match metric' match statement. `arg' is METRIC value */ @@ -98,29 +94,25 @@ static const struct route_map_rule_cmd route_match_metric_cmd = { /* `match interface IFNAME' */ /* Match function return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_interface(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_interface(void *rule, const struct prefix *prefix, void *object) { struct rip_info *rinfo; struct interface *ifp; char *ifname; - if (type == RMAP_RIP) { - ifname = rule; - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); + ifname = rule; + ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - if (!ifp) - return RMAP_NOMATCH; + if (!ifp) + return RMAP_NOMATCH; - rinfo = object; + rinfo = object; - if (rinfo->ifindex_out == ifp->ifindex - || rinfo->nh.ifindex == ifp->ifindex) - return RMAP_MATCH; - else - return RMAP_NOMATCH; - } - return RMAP_NOMATCH; + if (rinfo->ifindex_out == ifp->ifindex + || rinfo->nh.ifindex == ifp->ifindex) + return RMAP_MATCH; + else + return RMAP_NOMATCH; } /* Route map `match interface' match statement. `arg' is IFNAME value */ @@ -148,30 +140,25 @@ static const struct route_map_rule_cmd route_match_interface_cmd = { /* Match function return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_ip_next_hop(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_next_hop(void *rule, const struct prefix *prefix, void *object) { struct access_list *alist; struct rip_info *rinfo; struct prefix_ipv4 p; - if (type == RMAP_RIP) { - rinfo = object; - p.family = AF_INET; - p.prefix = (rinfo->nh.gate.ipv4.s_addr != INADDR_ANY) - ? rinfo->nh.gate.ipv4 - : rinfo->from; - p.prefixlen = IPV4_MAX_BITLEN; + rinfo = object; + p.family = AF_INET; + p.prefix = (rinfo->nh.gate.ipv4.s_addr != INADDR_ANY) + ? rinfo->nh.gate.ipv4 + : rinfo->from; + p.prefixlen = IPV4_MAX_BITLEN; - alist = access_list_lookup(AFI_IP, (char *)rule); - if (alist == NULL) - return RMAP_NOMATCH; + alist = access_list_lookup(AFI_IP, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; - return (access_list_apply(alist, &p) == FILTER_DENY - ? RMAP_NOMATCH - : RMAP_MATCH); - } - return RMAP_NOMATCH; + return (access_list_apply(alist, &p) == FILTER_DENY ? RMAP_NOMATCH + : RMAP_MATCH); } /* Route map `ip next-hop' match statement. `arg' should be @@ -199,29 +186,25 @@ static const struct route_map_rule_cmd route_match_ip_next_hop_cmd = { static enum route_map_cmd_result_t route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { struct prefix_list *plist; struct rip_info *rinfo; struct prefix_ipv4 p; - if (type == RMAP_RIP) { - rinfo = object; - p.family = AF_INET; - p.prefix = (rinfo->nh.gate.ipv4.s_addr != INADDR_ANY) - ? rinfo->nh.gate.ipv4 - : rinfo->from; - p.prefixlen = IPV4_MAX_BITLEN; + rinfo = object; + p.family = AF_INET; + p.prefix = (rinfo->nh.gate.ipv4.s_addr != INADDR_ANY) + ? rinfo->nh.gate.ipv4 + : rinfo->from; + p.prefixlen = IPV4_MAX_BITLEN; - plist = prefix_list_lookup(AFI_IP, (char *)rule); - if (plist == NULL) - return RMAP_NOMATCH; + plist = prefix_list_lookup(AFI_IP, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; - return (prefix_list_apply(plist, &p) == PREFIX_DENY - ? RMAP_NOMATCH - : RMAP_MATCH); - } - return RMAP_NOMATCH; + return (prefix_list_apply(plist, &p) == PREFIX_DENY ? RMAP_NOMATCH + : RMAP_MATCH); } static void *route_match_ip_next_hop_prefix_list_compile(const char *arg) @@ -246,11 +229,11 @@ static const struct route_map_rule_cmd static enum route_map_cmd_result_t route_match_ip_next_hop_type(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { struct rip_info *rinfo; - if (type == RMAP_RIP && prefix->family == AF_INET) { + if (prefix->family == AF_INET) { rinfo = (struct rip_info *)object; if (!rinfo) return RMAP_NOMATCH; @@ -284,21 +267,16 @@ static const struct route_map_rule_cmd /* Match function should return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_ip_address(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_address(void *rule, const struct prefix *prefix, void *object) { struct access_list *alist; - if (type == RMAP_RIP) { - alist = access_list_lookup(AFI_IP, (char *)rule); - if (alist == NULL) - return RMAP_NOMATCH; + alist = access_list_lookup(AFI_IP, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; - return (access_list_apply(alist, prefix) == FILTER_DENY - ? RMAP_NOMATCH - : RMAP_MATCH); - } - return RMAP_NOMATCH; + return (access_list_apply(alist, prefix) == FILTER_DENY ? RMAP_NOMATCH + : RMAP_MATCH); } /* Route map `ip address' match statement. `arg' should be @@ -326,20 +304,16 @@ static const struct route_map_rule_cmd route_match_ip_address_cmd = { static enum route_map_cmd_result_t route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { struct prefix_list *plist; - if (type == RMAP_RIP) { - plist = prefix_list_lookup(AFI_IP, (char *)rule); - if (plist == NULL) - return RMAP_NOMATCH; + plist = prefix_list_lookup(AFI_IP, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; - return (prefix_list_apply(plist, prefix) == PREFIX_DENY - ? RMAP_NOMATCH - : RMAP_MATCH); - } - return RMAP_NOMATCH; + return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH + : RMAP_MATCH); } static void *route_match_ip_address_prefix_list_compile(const char *arg) @@ -363,25 +337,21 @@ static const struct route_map_rule_cmd /* `match tag TAG' */ /* Match function return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_tag(void *rule, const struct prefix *p, route_map_object_t type, - void *object) +route_match_tag(void *rule, const struct prefix *p, void *object) { route_tag_t *tag; struct rip_info *rinfo; route_tag_t rinfo_tag; - if (type == RMAP_RIP) { - tag = rule; - rinfo = object; + tag = rule; + rinfo = object; - /* The information stored by rinfo is host ordered. */ - rinfo_tag = rinfo->tag; - if (rinfo_tag == *tag) - return RMAP_MATCH; - else - return RMAP_NOMATCH; - } - return RMAP_NOMATCH; + /* The information stored by rinfo is host ordered. */ + rinfo_tag = rinfo->tag; + if (rinfo_tag == *tag) + return RMAP_MATCH; + else + return RMAP_NOMATCH; } /* Route map commands for tag matching. */ @@ -396,33 +366,30 @@ static const struct route_map_rule_cmd route_match_tag_cmd = { /* Set metric to attribute. */ static enum route_map_cmd_result_t -route_set_metric(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_metric(void *rule, const struct prefix *prefix, void *object) { - if (type == RMAP_RIP) { - struct rip_metric_modifier *mod; - struct rip_info *rinfo; + struct rip_metric_modifier *mod; + struct rip_info *rinfo; - mod = rule; - rinfo = object; + mod = rule; + rinfo = object; - if (!mod->used) - return RMAP_OKAY; + if (!mod->used) + return RMAP_OKAY; - if (mod->type == metric_increment) - rinfo->metric_out += mod->metric; - else if (mod->type == metric_decrement) - rinfo->metric_out -= mod->metric; - else if (mod->type == metric_absolute) - rinfo->metric_out = mod->metric; + if (mod->type == metric_increment) + rinfo->metric_out += mod->metric; + else if (mod->type == metric_decrement) + rinfo->metric_out -= mod->metric; + else if (mod->type == metric_absolute) + rinfo->metric_out = mod->metric; - if ((signed int)rinfo->metric_out < 1) - rinfo->metric_out = 1; - if (rinfo->metric_out > RIP_METRIC_INFINITY) - rinfo->metric_out = RIP_METRIC_INFINITY; + if ((signed int)rinfo->metric_out < 1) + rinfo->metric_out = 1; + if (rinfo->metric_out > RIP_METRIC_INFINITY) + rinfo->metric_out = RIP_METRIC_INFINITY; - rinfo->metric_set = 1; - } + rinfo->metric_set = 1; return RMAP_OKAY; } @@ -495,22 +462,20 @@ static const struct route_map_rule_cmd route_set_metric_cmd = { /* `set ip next-hop IP_ADDRESS' */ /* Set nexthop to object. ojbect must be pointer to struct attr. */ -static enum route_map_cmd_result_t route_set_ip_nexthop(void *rule, - const struct prefix *prefix, - route_map_object_t type, - void *object) +static enum route_map_cmd_result_t +route_set_ip_nexthop(void *rule, const struct prefix *prefix, + + void *object) { struct in_addr *address; struct rip_info *rinfo; - if (type == RMAP_RIP) { - /* Fetch routemap's rule information. */ - address = rule; - rinfo = object; + /* Fetch routemap's rule information. */ + address = rule; + rinfo = object; - /* Set next hop value. */ - rinfo->nexthop_out = *address; - } + /* Set next hop value. */ + rinfo->nexthop_out = *address; return RMAP_OKAY; } @@ -552,20 +517,17 @@ static const struct route_map_rule_cmd route_set_ip_nexthop_cmd = { /* Set tag to object. ojbect must be pointer to struct attr. */ static enum route_map_cmd_result_t -route_set_tag(void *rule, const struct prefix *prefix, route_map_object_t type, - void *object) +route_set_tag(void *rule, const struct prefix *prefix, void *object) { route_tag_t *tag; struct rip_info *rinfo; - if (type == RMAP_RIP) { - /* Fetch routemap's rule information. */ - tag = rule; - rinfo = object; + /* Fetch routemap's rule information. */ + tag = rule; + rinfo = object; - /* Set next hop value. */ - rinfo->tag_out = *tag; - } + /* Set next hop value. */ + rinfo->tag_out = *tag; return RMAP_OKAY; } diff --git a/ripd/ripd.c b/ripd/ripd.c index 059a0e2efd..0cec847f05 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -462,7 +462,7 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from, if (ri->routemap[RIP_FILTER_IN]) { /* The object should be of the type of rip_info */ ret = route_map_apply(ri->routemap[RIP_FILTER_IN], - (struct prefix *)&p, RMAP_RIP, &newinfo); + (struct prefix *)&p, &newinfo); if (ret == RMAP_DENYMATCH) { if (IS_RIP_DEBUG_PACKET) @@ -2251,7 +2251,7 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to, if (ri->routemap[RIP_FILTER_OUT]) { ret = route_map_apply( ri->routemap[RIP_FILTER_OUT], - (struct prefix *)p, RMAP_RIP, rinfo); + (struct prefix *)p, rinfo); if (ret == RMAP_DENYMATCH) { if (IS_RIP_DEBUG_PACKET) @@ -2267,7 +2267,7 @@ void rip_output_process(struct connected *ifc, struct sockaddr_in *to, && rinfo->sub_type != RIP_ROUTE_INTERFACE) { ret = route_map_apply( rip->redist[rinfo->type].route_map.map, - (struct prefix *)p, RMAP_RIP, rinfo); + (struct prefix *)p, rinfo); if (ret == RMAP_DENYMATCH) { if (IS_RIP_DEBUG_PACKET) diff --git a/ripngd/ripng_routemap.c b/ripngd/ripng_routemap.c index b5f80d2ab0..9aed8d6963 100644 --- a/ripngd/ripng_routemap.c +++ b/ripngd/ripng_routemap.c @@ -39,21 +39,19 @@ struct rip_metric_modifier { /* `match metric METRIC' */ /* Match function return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_metric(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_metric(void *rule, const struct prefix *prefix, void *object) { uint32_t *metric; struct ripng_info *rinfo; - if (type == RMAP_RIPNG) { - metric = rule; - rinfo = object; + metric = rule; + rinfo = object; + + if (rinfo->metric == *metric) + return RMAP_MATCH; + else + return RMAP_NOMATCH; - if (rinfo->metric == *metric) - return RMAP_MATCH; - else - return RMAP_NOMATCH; - } return RMAP_NOMATCH; } @@ -89,27 +87,25 @@ static const struct route_map_rule_cmd route_match_metric_cmd = { /* `match interface IFNAME' */ /* Match function return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_interface(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_interface(void *rule, const struct prefix *prefix, void *object) { struct ripng_info *rinfo; struct interface *ifp; char *ifname; - if (type == RMAP_RIPNG) { - ifname = rule; - ifp = if_lookup_by_name(ifname, VRF_DEFAULT); + ifname = rule; + ifp = if_lookup_by_name(ifname, VRF_DEFAULT); - if (!ifp) - return RMAP_NOMATCH; + if (!ifp) + return RMAP_NOMATCH; - rinfo = object; + rinfo = object; + + if (rinfo->ifindex == ifp->ifindex) + return RMAP_MATCH; + else + return RMAP_NOMATCH; - if (rinfo->ifindex == ifp->ifindex) - return RMAP_MATCH; - else - return RMAP_NOMATCH; - } return RMAP_NOMATCH; } @@ -135,27 +131,24 @@ static const struct route_map_rule_cmd route_match_interface_cmd = { /* Match function return 1 if match is success else return zero. */ static enum route_map_cmd_result_t route_match_tag(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) { route_tag_t *tag; struct ripng_info *rinfo; route_tag_t rinfo_tag; - if (type == RMAP_RIPNG) { - tag = rule; - rinfo = object; + tag = rule; + rinfo = object; - /* The information stored by rinfo is host ordered. */ - rinfo_tag = rinfo->tag; - if (rinfo_tag == *tag) - return RMAP_MATCH; - else - return RMAP_NOMATCH; - } - return RMAP_NOMATCH; + /* The information stored by rinfo is host ordered. */ + rinfo_tag = rinfo->tag; + if (rinfo_tag == *tag) + return RMAP_MATCH; + else + return RMAP_NOMATCH; } + static const struct route_map_rule_cmd route_match_tag_cmd = { "tag", route_match_tag, @@ -167,33 +160,31 @@ static const struct route_map_rule_cmd route_match_tag_cmd = { /* Set metric to attribute. */ static enum route_map_cmd_result_t -route_set_metric(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_set_metric(void *rule, const struct prefix *prefix, void *object) { - if (type == RMAP_RIPNG) { - struct rip_metric_modifier *mod; - struct ripng_info *rinfo; + struct rip_metric_modifier *mod; + struct ripng_info *rinfo; - mod = rule; - rinfo = object; + mod = rule; + rinfo = object; - if (!mod->used) - return RMAP_OKAY; + if (!mod->used) + return RMAP_OKAY; - if (mod->type == metric_increment) - rinfo->metric_out += mod->metric; - else if (mod->type == metric_decrement) - rinfo->metric_out -= mod->metric; - else if (mod->type == metric_absolute) - rinfo->metric_out = mod->metric; + if (mod->type == metric_increment) + rinfo->metric_out += mod->metric; + else if (mod->type == metric_decrement) + rinfo->metric_out -= mod->metric; + else if (mod->type == metric_absolute) + rinfo->metric_out = mod->metric; - if (rinfo->metric_out < 1) - rinfo->metric_out = 1; - if (rinfo->metric_out > RIPNG_METRIC_INFINITY) - rinfo->metric_out = RIPNG_METRIC_INFINITY; + if (rinfo->metric_out < 1) + rinfo->metric_out = 1; + if (rinfo->metric_out > RIPNG_METRIC_INFINITY) + rinfo->metric_out = RIPNG_METRIC_INFINITY; + + rinfo->metric_set = 1; - rinfo->metric_set = 1; - } return RMAP_OKAY; } @@ -265,20 +256,17 @@ static const struct route_map_rule_cmd route_set_metric_cmd = { /* Set nexthop to object. ojbect must be pointer to struct attr. */ static enum route_map_cmd_result_t -route_set_ipv6_nexthop_local(void *rule, const struct prefix *p, - route_map_object_t type, void *object) +route_set_ipv6_nexthop_local(void *rule, const struct prefix *p, void *object) { struct in6_addr *address; struct ripng_info *rinfo; - if (type == RMAP_RIPNG) { - /* Fetch routemap's rule information. */ - address = rule; - rinfo = object; + /* Fetch routemap's rule information. */ + address = rule; + rinfo = object; - /* Set next hop value. */ - rinfo->nexthop_out = *address; - } + /* Set next hop value. */ + rinfo->nexthop_out = *address; return RMAP_OKAY; } @@ -321,20 +309,17 @@ static const struct route_map_rule_cmd /* Set tag to object. ojbect must be pointer to struct attr. */ static enum route_map_cmd_result_t -route_set_tag(void *rule, const struct prefix *prefix, route_map_object_t type, - void *object) +route_set_tag(void *rule, const struct prefix *prefix, void *object) { route_tag_t *tag; struct ripng_info *rinfo; - if (type == RMAP_RIPNG) { - /* Fetch routemap's rule information. */ - tag = rule; - rinfo = object; + /* Fetch routemap's rule information. */ + tag = rule; + rinfo = object; - /* Set next hop value. */ - rinfo->tag_out = *tag; - } + /* Set next hop value. */ + rinfo->tag_out = *tag; return RMAP_OKAY; } diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c index 8d9249e4ae..1ebdae43fb 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -748,8 +748,7 @@ static void ripng_route_process(struct rte *rte, struct sockaddr_in6 *from, /* Modify entry. */ if (ri->routemap[RIPNG_FILTER_IN]) { ret = route_map_apply(ri->routemap[RIPNG_FILTER_IN], - (struct prefix *)&p, RMAP_RIPNG, - &newinfo); + (struct prefix *)&p, &newinfo); if (ret == RMAP_DENYMATCH) { if (IS_RIPNG_DEBUG_PACKET) @@ -1661,7 +1660,7 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to, if (ri->routemap[RIPNG_FILTER_OUT]) { ret = route_map_apply( ri->routemap[RIPNG_FILTER_OUT], - (struct prefix *)p, RMAP_RIPNG, rinfo); + (struct prefix *)p, rinfo); if (ret == RMAP_DENYMATCH) { if (IS_RIPNG_DEBUG_PACKET) @@ -1677,7 +1676,7 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to, ret = route_map_apply(ripng->redist[rinfo->type] .route_map.map, (struct prefix *)p, - RMAP_RIPNG, rinfo); + rinfo); if (ret == RMAP_DENYMATCH) { if (IS_RIPNG_DEBUG_PACKET) @@ -1773,8 +1772,7 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to, ret = route_map_apply( ri->routemap[RIPNG_FILTER_OUT], - (struct prefix *)p, RMAP_RIPNG, - &newinfo); + (struct prefix *)p, &newinfo); if (ret == RMAP_DENYMATCH) { if (IS_RIPNG_DEBUG_PACKET) diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c index 231de6403d..7a335fca3b 100644 --- a/sharpd/sharp_zebra.c +++ b/sharpd/sharp_zebra.c @@ -301,7 +301,8 @@ static int route_notify_owner(ZAPI_CALLBACK_ARGS) enum zapi_route_notify_owner note; uint32_t table; - if (!zapi_route_notify_decode(zclient->ibuf, &p, &table, ¬e)) + if (!zapi_route_notify_decode(zclient->ibuf, &p, &table, ¬e, + NULL, NULL)) return -1; switch (note) { diff --git a/staticd/static_memory.h b/staticd/static_memory.h index e9cc7ba469..077cd0f32b 100644 --- a/staticd/static_memory.h +++ b/staticd/static_memory.h @@ -23,6 +23,7 @@ DECLARE_MGROUP(STATIC) +DECLARE_MTYPE(STATIC_ROUTE); DECLARE_MTYPE(STATIC_NEXTHOP); DECLARE_MTYPE(STATIC_PATH); diff --git a/staticd/static_routes.c b/staticd/static_routes.c index d105b2123f..05355c48fe 100644 --- a/staticd/static_routes.c +++ b/staticd/static_routes.c @@ -35,7 +35,7 @@ #include "static_zebra.h" #include "static_debug.h" -DEFINE_MTYPE_STATIC(STATIC, STATIC_ROUTE, "Static Route Info"); +DEFINE_MTYPE(STATIC, STATIC_ROUTE, "Static Route Info"); DEFINE_MTYPE(STATIC, STATIC_PATH, "Static Path"); /* Install static path into rib. */ @@ -546,19 +546,15 @@ void static_fixup_vrf_ids(struct static_vrf *enable_svrf) svrf = vrf->info; /* Install any static routes configured for this VRF. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) { - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { - stable = svrf->stable[afi][safi]; - if (!stable) - continue; + FOREACH_AFI_SAFI (afi, safi) { + stable = svrf->stable[afi][safi]; + if (!stable) + continue; - static_fixup_vrf(enable_svrf, stable, - afi, safi); + static_fixup_vrf(enable_svrf, stable, afi, safi); - if (enable_svrf == svrf) - static_enable_vrf(svrf, stable, - afi, safi); - } + if (enable_svrf == svrf) + static_enable_vrf(svrf, stable, afi, safi); } } } @@ -649,20 +645,17 @@ void static_cleanup_vrf_ids(struct static_vrf *disable_svrf) svrf = vrf->info; /* Uninstall any static routes configured for this VRF. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) { - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { - struct route_table *stable; + FOREACH_AFI_SAFI (afi, safi) { + struct route_table *stable; - stable = svrf->stable[afi][safi]; - if (!stable) - continue; + stable = svrf->stable[afi][safi]; + if (!stable) + continue; - static_cleanup_vrf(disable_svrf, stable, - afi, safi); + static_cleanup_vrf(disable_svrf, stable, afi, safi); - if (disable_svrf == svrf) - static_disable_vrf(stable, afi, safi); - } + if (disable_svrf == svrf) + static_disable_vrf(stable, afi, safi); } } } @@ -725,14 +718,12 @@ void static_install_intf_nh(struct interface *ifp) continue; /* Install any static routes configured for this interface. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) { - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { - stable = svrf->stable[afi][safi]; - if (!stable) - continue; + FOREACH_AFI_SAFI (afi, safi) { + stable = svrf->stable[afi][safi]; + if (!stable) + continue; - static_fixup_intf_nh(stable, ifp, afi, safi); - } + static_fixup_intf_nh(stable, ifp, afi, safi); } } } diff --git a/staticd/static_vrf.c b/staticd/static_vrf.c index 39b86787ff..83894e9267 100644 --- a/staticd/static_vrf.c +++ b/staticd/static_vrf.c @@ -38,6 +38,10 @@ static void zebra_stable_node_cleanup(struct route_table *table, struct static_nexthop *nh; struct static_path *pn; struct static_route_info *si; + struct route_table *src_table; + struct route_node *src_node; + struct static_path *src_pn; + struct static_route_info *src_si; si = node->info; @@ -51,6 +55,37 @@ static void zebra_stable_node_cleanup(struct route_table *table, static_path_list_del(&si->path_list, pn); XFREE(MTYPE_STATIC_PATH, pn); } + + /* clean up for dst table */ + src_table = srcdest_srcnode_table(node); + if (src_table) { + /* This means the route_node is part of the top + * hierarchy and refers to a destination prefix. + */ + for (src_node = route_top(src_table); src_node; + src_node = route_next(src_node)) { + src_si = src_node->info; + + frr_each_safe(static_path_list, + &src_si->path_list, src_pn) { + frr_each_safe(static_nexthop_list, + &src_pn->nexthop_list, + nh) { + static_nexthop_list_del( + &src_pn->nexthop_list, + nh); + XFREE(MTYPE_STATIC_NEXTHOP, nh); + } + static_path_list_del(&src_si->path_list, + src_pn); + XFREE(MTYPE_STATIC_PATH, src_pn); + } + + XFREE(MTYPE_STATIC_ROUTE, src_node->info); + } + } + + XFREE(MTYPE_STATIC_ROUTE, node->info); } } @@ -203,14 +238,12 @@ int static_vrf_has_config(struct static_vrf *svrf) * NOTE: This is a don't care for the default VRF, but we go through * the motions to keep things consistent. */ - for (afi = AFI_IP; afi < AFI_MAX; afi++) { - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { - table = svrf->stable[afi][safi]; - if (!table) - continue; - if (route_table_count(table)) - return 1; - } + FOREACH_AFI_SAFI (afi, safi) { + table = svrf->stable[afi][safi]; + if (!table) + continue; + if (route_table_count(table)) + return 1; } return 0; diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index a9b570de83..0bccbfbead 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -110,7 +110,8 @@ static int route_notify_owner(ZAPI_CALLBACK_ARGS) enum zapi_route_notify_owner note; uint32_t table_id; - if (!zapi_route_notify_decode(zclient->ibuf, &p, &table_id, ¬e)) + if (!zapi_route_notify_decode(zclient->ibuf, &p, &table_id, ¬e, + NULL, NULL)) return -1; switch (note) { diff --git a/tests/bgpd/test_mpath.c b/tests/bgpd/test_mpath.c index 99fb7b620d..520c460f15 100644 --- a/tests/bgpd/test_mpath.c +++ b/tests/bgpd/test_mpath.c @@ -106,15 +106,13 @@ static struct bgp *bgp_create_fake(as_t *as, const char *name) // bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp; bgp_evpn_init(bgp); - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { - bgp->route[afi][safi] = bgp_table_init(bgp, afi, safi); - bgp->aggregate[afi][safi] = bgp_table_init( - bgp, afi, safi); - bgp->rib[afi][safi] = bgp_table_init(bgp, afi, safi); - bgp->maxpaths[afi][safi].maxpaths_ebgp = MULTIPATH_NUM; - bgp->maxpaths[afi][safi].maxpaths_ibgp = MULTIPATH_NUM; - } + FOREACH_AFI_SAFI (afi, safi) { + bgp->route[afi][safi] = bgp_table_init(bgp, afi, safi); + bgp->aggregate[afi][safi] = bgp_table_init(bgp, afi, safi); + bgp->rib[afi][safi] = bgp_table_init(bgp, afi, safi); + bgp->maxpaths[afi][safi].maxpaths_ebgp = MULTIPATH_NUM; + bgp->maxpaths[afi][safi].maxpaths_ibgp = MULTIPATH_NUM; + } bgp_scan_init(bgp); bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF; @@ -152,36 +150,33 @@ static int run_bgp_cfg_maximum_paths(testcase_t *t) int test_result = TEST_PASSED; bgp = t->tmp_data; - for (afi = AFI_IP; afi < AFI_MAX; afi++) - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { - /* test bgp_maximum_paths_set */ - api_result = bgp_maximum_paths_set( - bgp, afi, safi, BGP_PEER_EBGP, 10, 0); - EXPECT_TRUE(api_result == 0, test_result); - api_result = bgp_maximum_paths_set( - bgp, afi, safi, BGP_PEER_IBGP, 10, 0); - EXPECT_TRUE(api_result == 0, test_result); - EXPECT_TRUE(bgp->maxpaths[afi][safi].maxpaths_ebgp - == 10, - test_result); - EXPECT_TRUE(bgp->maxpaths[afi][safi].maxpaths_ibgp - == 10, - test_result); - - /* test bgp_maximum_paths_unset */ - api_result = bgp_maximum_paths_unset(bgp, afi, safi, - BGP_PEER_EBGP); - EXPECT_TRUE(api_result == 0, test_result); - api_result = bgp_maximum_paths_unset(bgp, afi, safi, - BGP_PEER_IBGP); - EXPECT_TRUE(api_result == 0, test_result); - EXPECT_TRUE((bgp->maxpaths[afi][safi].maxpaths_ebgp - == MULTIPATH_NUM), - test_result); - EXPECT_TRUE((bgp->maxpaths[afi][safi].maxpaths_ibgp - == MULTIPATH_NUM), - test_result); - } + FOREACH_AFI_SAFI (afi, safi) { + /* test bgp_maximum_paths_set */ + api_result = bgp_maximum_paths_set(bgp, afi, safi, + BGP_PEER_EBGP, 10, 0); + EXPECT_TRUE(api_result == 0, test_result); + api_result = bgp_maximum_paths_set(bgp, afi, safi, + BGP_PEER_IBGP, 10, 0); + EXPECT_TRUE(api_result == 0, test_result); + EXPECT_TRUE(bgp->maxpaths[afi][safi].maxpaths_ebgp == 10, + test_result); + EXPECT_TRUE(bgp->maxpaths[afi][safi].maxpaths_ibgp == 10, + test_result); + + /* test bgp_maximum_paths_unset */ + api_result = + bgp_maximum_paths_unset(bgp, afi, safi, BGP_PEER_EBGP); + EXPECT_TRUE(api_result == 0, test_result); + api_result = + bgp_maximum_paths_unset(bgp, afi, safi, BGP_PEER_IBGP); + EXPECT_TRUE(api_result == 0, test_result); + EXPECT_TRUE((bgp->maxpaths[afi][safi].maxpaths_ebgp + == MULTIPATH_NUM), + test_result); + EXPECT_TRUE((bgp->maxpaths[afi][safi].maxpaths_ibgp + == MULTIPATH_NUM), + test_result); + } return test_result; } diff --git a/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py b/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py index 12069a12dc..54a3c699f3 100644 --- a/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py +++ b/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py @@ -292,6 +292,10 @@ def test_modify_ecmp_max_paths(request, ecmp_num, test_type): input_dict_1 = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}} logger.info("Verifying %s routes on r3", addr_type) + + # Only test the count of nexthops; the actual nexthop addresses + # can vary and are not deterministic. + # result = verify_rib( tgen, addr_type, @@ -299,7 +303,9 @@ def test_modify_ecmp_max_paths(request, ecmp_num, test_type): input_dict_1, next_hop=NEXT_HOPS[addr_type][: int(ecmp_num)], protocol=protocol, + count_only=True ) + assert result is True, "Testcase {} : Failed \n Error: {}".format( tc_name, result ) diff --git a/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py b/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py index 50aa281d34..73724ac069 100644 --- a/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py +++ b/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py @@ -293,6 +293,10 @@ def test_modify_ecmp_max_paths(request, ecmp_num, test_type): input_dict_1 = {"r3": {"static_routes": [{"network": NETWORK[addr_type]}]}} logger.info("Verifying %s routes on r3", addr_type) + + # Test only the count of nexthops, not the specific nexthop addresses - + # they're not deterministic + # result = verify_rib( tgen, addr_type, @@ -300,7 +304,9 @@ def test_modify_ecmp_max_paths(request, ecmp_num, test_type): input_dict_1, next_hop=NEXT_HOPS[addr_type][: int(ecmp_num)], protocol=protocol, + count_only=True ) + assert result is True, "Testcase {} : Failed \n Error: {}".format( tc_name, result ) diff --git a/tests/topotests/bgp_suppress_fib/r1/bgpd.conf b/tests/topotests/bgp_suppress_fib/r1/bgpd.conf new file mode 100644 index 0000000000..69c563d37c --- /dev/null +++ b/tests/topotests/bgp_suppress_fib/r1/bgpd.conf @@ -0,0 +1,15 @@ +! exit1 +router bgp 1 + no bgp ebgp-requires-policy + neighbor 10.0.0.2 remote-as 2 + + address-family ipv4 unicast + redistribute static + neighbor 10.0.0.2 route-map rmap out + exit-address-family + +ip prefix-list plist seq 5 permit any + +route-map rmap permit 1 + match ip address prefix-list plist +! diff --git a/tests/topotests/bgp_suppress_fib/r1/zebra.conf b/tests/topotests/bgp_suppress_fib/r1/zebra.conf new file mode 100644 index 0000000000..7b442164ff --- /dev/null +++ b/tests/topotests/bgp_suppress_fib/r1/zebra.conf @@ -0,0 +1,9 @@ +! exit1 +interface r1-eth0 + ip address 10.0.0.1/30 +! +ip forwarding +! +ip route 40.0.0.0/8 blackhole +ip route 50.0.0.0/8 blackhole +! diff --git a/tests/topotests/bgp_suppress_fib/r2/bgpd.conf b/tests/topotests/bgp_suppress_fib/r2/bgpd.conf new file mode 100644 index 0000000000..8321c915e3 --- /dev/null +++ b/tests/topotests/bgp_suppress_fib/r2/bgpd.conf @@ -0,0 +1,6 @@ +! +router bgp 2 + no bgp ebgp-requires-policy + bgp suppress-fib-pending + neighbor 10.0.0.1 remote-as 1 + neighbor 10.0.0.10 remote-as 3 diff --git a/tests/topotests/bgp_suppress_fib/r2/zebra.conf b/tests/topotests/bgp_suppress_fib/r2/zebra.conf new file mode 100644 index 0000000000..443fffc703 --- /dev/null +++ b/tests/topotests/bgp_suppress_fib/r2/zebra.conf @@ -0,0 +1,13 @@ +! +interface r2-eth0 + ip address 10.0.0.2/30 +! +interface r2-eth1 + ip address 10.0.0.9/30 + +access-list access seq 5 permit 40.0.0.0/8 + +route-map LIMIT permit 10 + match ip address access + +ip protocol bgp route-map LIMIT diff --git a/tests/topotests/bgp_suppress_fib/r3/bgpd.conf b/tests/topotests/bgp_suppress_fib/r3/bgpd.conf new file mode 100644 index 0000000000..11715d45d7 --- /dev/null +++ b/tests/topotests/bgp_suppress_fib/r3/bgpd.conf @@ -0,0 +1,9 @@ +! +router bgp 3 + no bgp ebgp-requires-policy + neighbor 10.0.0.9 remote-as 2 + +route-map rmap permit 1 + match ip address prefix-list plist + ! +! diff --git a/tests/topotests/bgp_suppress_fib/r3/v4_route.json b/tests/topotests/bgp_suppress_fib/r3/v4_route.json new file mode 100644 index 0000000000..19294eb492 --- /dev/null +++ b/tests/topotests/bgp_suppress_fib/r3/v4_route.json @@ -0,0 +1,29 @@ +{ + "40.0.0.0\/8":[ + { + "prefix":"40.0.0.0\/8", + "protocol":"bgp", + "selected":true, + "destSelected":true, + "distance":20, + "metric":0, + "installed":true, + "table":254, + "internalStatus":16, + "internalFlags":8, + "internalNextHopNum":1, + "internalNextHopActiveNum":1, + "nexthops":[ + { + "flags":3, + "fib":true, + "ip":"10.0.0.9", + "afi":"ipv4", + "interfaceIndex":2, + "interfaceName":"r3-eth0", + "active":true + } + ] + } + ] +} diff --git a/tests/topotests/bgp_suppress_fib/r3/v4_route2.json b/tests/topotests/bgp_suppress_fib/r3/v4_route2.json new file mode 100644 index 0000000000..a35d49e9e8 --- /dev/null +++ b/tests/topotests/bgp_suppress_fib/r3/v4_route2.json @@ -0,0 +1,4 @@ +{ + "0.0.0.0\/0":[ + ] +} diff --git a/tests/topotests/bgp_suppress_fib/r3/zebra.conf b/tests/topotests/bgp_suppress_fib/r3/zebra.conf new file mode 100644 index 0000000000..793b043a7b --- /dev/null +++ b/tests/topotests/bgp_suppress_fib/r3/zebra.conf @@ -0,0 +1,6 @@ +! +interface r3-eth0 + ip address 10.0.0.10/30 +! +ip forwarding +! diff --git a/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py b/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py new file mode 100644 index 0000000000..cf8be5f44f --- /dev/null +++ b/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python + +# +# test_bgp_suppress_fib.py +# +# Copyright (c) 2019 by +# +# 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. +# + +""" +""" + +import os +import sys +import json +import time +import pytest +from functools import partial +from time import sleep + +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, *_args, **_opts): + tgen = get_topogen(self) + + for routern in range(1, 4): + tgen.add_router("r{}".format(routern)) + + switch = tgen.add_switch("s1") + switch.add_link(tgen.gears["r1"]) + switch.add_link(tgen.gears["r2"]) + + switch = tgen.add_switch("s2") + switch.add_link(tgen.gears["r2"]) + switch.add_link(tgen.gears["r3"]) + +def setup_module(mod): + tgen = Topogen(TemplateTopo, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + for i, (rname, router) in enumerate(router_list.items(), 1): + router.load_config( + TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)) + ) + router.load_config( + TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)) + ) + + tgen.start_router() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def test_bgp_route(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + r3 = tgen.gears["r3"] + + sleep(5) + + json_file = "{}/r3/v4_route.json".format(CWD) + expected = json.loads(open(json_file).read()) + + test_func = partial( + topotest.router_json_cmp, + r3, + "show ip route 40.0.0.0 json", + expected, + ) + _, result = topotest.run_and_expect(test_func, None, count=2, wait=0.5) + assertmsg = '"r3" JSON output mismatches' + assert result is None, assertmsg + + json_file = "{}/r3/v4_route2.json".format(CWD) + expected = json.loads(open(json_file).read()) + + test_func = partial( + topotest.router_json_cmp, + r3, + "show ip route 50.0.0.0 json", + expected, + ) + _, result = topotest.run_and_expect(test_func, None, count=3, wait=0.5) + assertmsg = '"r3" JSON output mismatches' + assert result is None, assertmsg + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py index d83f946c42..e42992e294 100644 --- a/tests/topotests/lib/common_config.py +++ b/tests/topotests/lib/common_config.py @@ -2559,6 +2559,7 @@ def verify_rib( tag=None, metric=None, fib=None, + count_only=False ): """ Data will be read from input_dict or input JSON file, API will generate @@ -2576,6 +2577,8 @@ def verify_rib( * `next_hop`[optional]: next_hop which needs to be verified, default: static * `protocol`[optional]: protocol, default = None + * `count_only`[optional]: count of nexthops only, not specific addresses, + default = False Usage ----- @@ -2739,7 +2742,23 @@ def verify_rib( for rib_r in rib_routes_json[st_rt][0]["nexthops"] ] - if found_hops: + # Check only the count of nexthops + if count_only: + if len(next_hop) == len(found_hops): + nh_found = True + else: + errormsg = ( + "Nexthops are missing for " + "route {} in RIB of router {}: " + "expected {}, found {}\n".format( + st_rt, dut, len(next_hop), + len(found_hops) + ) + ) + return errormsg + + # Check the actual nexthops + elif found_hops: missing_list_of_nexthops = set( found_hops ).difference(next_hop) @@ -3019,262 +3038,6 @@ def verify_fib_routes(tgen, addr_type, dut, input_dict, next_hop=None): for st_rt in ip_list: st_rt = str(ipaddress.ip_network(frr_unicode(st_rt))) - # st_rt = str(ipaddr.IPNetwork(unicode(st_rt))) - - _addr_type = validate_ip_address(st_rt) - if _addr_type != addr_type: - continue - - if st_rt in rib_routes_json: - st_found = True - found_routes.append(st_rt) - - if next_hop: - if type(next_hop) is not list: - next_hop = [next_hop] - - count = 0 - for nh in next_hop: - for nh_dict in rib_routes_json[st_rt][0][ - "nexthops" - ]: - if nh_dict["ip"] != nh: - continue - else: - count += 1 - - if count == len(next_hop): - nh_found = True - else: - missing_routes.append(st_rt) - errormsg = ( - "Nexthop {} is Missing" - " for route {} in " - "RIB of router {}\n".format( - next_hop, st_rt, dut - ) - ) - return errormsg - - else: - missing_routes.append(st_rt) - - if len(missing_routes) > 0: - errormsg = "[DUT: {}]: Missing route in FIB:" " {}".format( - dut, missing_routes - ) - return errormsg - - if nh_found: - logger.info( - "Found next_hop {} for all routes in RIB" - " of router {}\n".format(next_hop, dut) - ) - - if found_routes: - logger.info( - "[DUT: %s]: Verified routes in FIB, found" " routes are: %s\n", - dut, - found_routes, - ) - - continue - - if "bgp" in input_dict[routerInput]: - if ( - "advertise_networks" - not in input_dict[routerInput]["bgp"]["address_family"][addr_type][ - "unicast" - ] - ): - continue - - found_routes = [] - missing_routes = [] - advertise_network = input_dict[routerInput]["bgp"]["address_family"][ - addr_type - ]["unicast"]["advertise_networks"] - - # Continue if there are no network advertise - if len(advertise_network) == 0: - continue - - for advertise_network_dict in advertise_network: - if "vrf" in advertise_network_dict: - cmd = "{} vrf {} json".format(command, static_route["vrf"]) - else: - cmd = "{} json".format(command) - - rib_routes_json = run_frr_cmd(rnode, cmd, isjson=True) - - # Verifying output dictionary rib_routes_json is not empty - if bool(rib_routes_json) is False: - errormsg = "No route found in rib of router {}..".format(router) - return errormsg - - start_ip = advertise_network_dict["network"] - if "no_of_network" in advertise_network_dict: - no_of_network = advertise_network_dict["no_of_network"] - else: - no_of_network = 1 - - # Generating IPs for verification - ip_list = generate_ips(start_ip, no_of_network) - st_found = False - nh_found = False - - for st_rt in ip_list: - # st_rt = str(ipaddr.IPNetwork(unicode(st_rt))) - st_rt = str(ipaddress.ip_network(frr_unicode(st_rt))) - - _addr_type = validate_ip_address(st_rt) - if _addr_type != addr_type: - continue - - if st_rt in rib_routes_json: - st_found = True - found_routes.append(st_rt) - - if next_hop: - if type(next_hop) is not list: - next_hop = [next_hop] - - count = 0 - for nh in next_hop: - for nh_dict in rib_routes_json[st_rt][0]["nexthops"]: - if nh_dict["ip"] != nh: - continue - else: - count += 1 - - if count == len(next_hop): - nh_found = True - else: - missing_routes.append(st_rt) - errormsg = ( - "Nexthop {} is Missing" - " for route {} in " - "RIB of router {}\n".format(next_hop, st_rt, dut) - ) - return errormsg - else: - missing_routes.append(st_rt) - - if len(missing_routes) > 0: - errormsg = "[DUT: {}]: Missing route in FIB: " "{} \n".format( - dut, missing_routes - ) - return errormsg - - if nh_found: - logger.info( - "Found next_hop {} for all routes in RIB" - " of router {}\n".format(next_hop, dut) - ) - - if found_routes: - logger.info( - "[DUT: {}]: Verified routes FIB" - ", found routes are: {}\n".format(dut, found_routes) - ) - - logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name)) - return True - - -@retry(attempts=5, wait=2, return_is_str=True, initial_wait=2) -def verify_fib_routes(tgen, addr_type, dut, input_dict, next_hop=None): - """ - Data will be read from input_dict or input JSON file, API will generate - same prefixes, which were redistributed by either create_static_routes() or - advertise_networks_using_network_command() and will verify next_hop and - each prefix/routes is present in "show ip/ipv6 fib json" - command o/p. - - Parameters - ---------- - * `tgen` : topogen object - * `addr_type` : ip type, ipv4/ipv6 - * `dut`: Device Under Test, for which user wants to test the data - * `input_dict` : input dict, has details of static routes - * `next_hop`[optional]: next_hop which needs to be verified, - default: static - - Usage - ----- - input_routes_r1 = { - "r1": { - "static_routes": [{ - "network": ["1.1.1.1/32], - "next_hop": "Null0", - "vrf": "RED" - }] - } - } - result = result = verify_fib_routes(tgen, "ipv4, "r1", input_routes_r1) - - Returns - ------- - errormsg(str) or True - """ - - logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name)) - - router_list = tgen.routers() - for routerInput in input_dict.keys(): - for router, rnode in router_list.items(): - if router != dut: - continue - - logger.info("Checking router %s FIB routes:", router) - - # Verifying RIB routes - if addr_type == "ipv4": - command = "show ip fib" - else: - command = "show ipv6 fib" - - found_routes = [] - missing_routes = [] - - if "static_routes" in input_dict[routerInput]: - static_routes = input_dict[routerInput]["static_routes"] - - for static_route in static_routes: - if "vrf" in static_route and static_route["vrf"] is not None: - - logger.info( - "[DUT: {}]: Verifying routes for VRF:" - " {}".format(router, static_route["vrf"]) - ) - - cmd = "{} vrf {}".format(command, static_route["vrf"]) - - else: - cmd = "{}".format(command) - - cmd = "{} json".format(cmd) - - rib_routes_json = run_frr_cmd(rnode, cmd, isjson=True) - - # Verifying output dictionary rib_routes_json is not empty - if bool(rib_routes_json) is False: - errormsg = "[DUT: {}]: No route found in fib".format(router) - return errormsg - - network = static_route["network"] - if "no_of_ip" in static_route: - no_of_ip = static_route["no_of_ip"] - else: - no_of_ip = 1 - - # Generating IPs for verification - ip_list = generate_ips(network, no_of_ip) - st_found = False - nh_found = False - - for st_rt in ip_list: - st_rt = str(ipaddress.ip_network(frr_unicode(st_rt))) _addr_type = validate_ip_address(st_rt) if _addr_type != addr_type: diff --git a/tests/topotests/route-scale/r1/installed.routes.json b/tests/topotests/route-scale/r1/installed.routes.json index 25d209f9eb..24a45dca81 100644 --- a/tests/topotests/route-scale/r1/installed.routes.json +++ b/tests/topotests/route-scale/r1/installed.routes.json @@ -6,11 +6,11 @@ "type":"connected" }, { - "fib":1000000, - "rib":1000000, + "fib":200000, + "rib":200000, "type":"sharp" } ], - "routesTotal":1000032, - "routesTotalFib":1000032 + "routesTotal":200032, + "routesTotalFib":200032 } diff --git a/tests/topotests/route-scale/test_route_scale.py b/tests/topotests/route-scale/test_route_scale.py index 8aedfc198c..bbd6ef8d60 100644 --- a/tests/topotests/route-scale/test_route_scale.py +++ b/tests/topotests/route-scale/test_route_scale.py @@ -122,15 +122,20 @@ def run_one_setup(r1, s): expected_installed = s["expect_in"] expected_removed = s["expect_rem"] - count = s["count"] + retries = s["retries"] wait = s["wait"] - logger.info("Testing 1 million routes X {} ecmp".format(s["ecmp"])) + for d in expected_installed["routes"]: + if d["type"] == "sharp": + count = d["rib"] + break + + logger.info("Testing {} routes X {} ecmp".format(count, s["ecmp"])) r1.vtysh_cmd( "sharp install route 1.0.0.0 \ - nexthop-group {} 1000000".format( - s["nhg"] + nexthop-group {} {}".format( + s["nhg"], count ), isjson=False, ) @@ -138,21 +143,21 @@ def run_one_setup(r1, s): test_func = partial( topotest.router_json_cmp, r1, "show ip route summary json", expected_installed ) - success, result = topotest.run_and_expect(test_func, None, count, wait) + success, result = topotest.run_and_expect(test_func, None, retries, wait) assert success, "Route scale test install failed:\n{}".format(result) output = r1.vtysh_cmd("sharp data route", isjson=False) - logger.info("1 million routes X {} ecmp installed".format(s["ecmp"])) + logger.info("{} routes X {} ecmp installed".format(count, s["ecmp"])) logger.info(output) - r1.vtysh_cmd("sharp remove route 1.0.0.0 1000000", isjson=False) + r1.vtysh_cmd("sharp remove route 1.0.0.0 {}".format(count), isjson=False) test_func = partial( topotest.router_json_cmp, r1, "show ip route summary json", expected_removed ) - success, result = topotest.run_and_expect(test_func, None, count, wait) + success, result = topotest.run_and_expect(test_func, None, retries, wait) assert success, "Route scale test remove failed:\n{}".format(result) output = r1.vtysh_cmd("sharp data route", isjson=False) - logger.info("1 million routes x {} ecmp removed".format(s["ecmp"])) + logger.info("{} routes x {} ecmp removed".format(count, s["ecmp"])) logger.info(output) @@ -174,7 +179,7 @@ def test_route_install(): # dict keys of params: ecmp number, corresponding nhg name, timeout, # number of times to wait - scale_keys = ["ecmp", "nhg", "wait", "count", "expect_in", "expect_rem"] + scale_keys = ["ecmp", "nhg", "wait", "retries", "expect_in", "expect_rem"] # Table of defaults, used for timeout values and 'expected' objects scale_defaults = dict( diff --git a/zebra/connected.c b/zebra/connected.c index 6a1efc3e65..70ea2e3805 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -41,6 +41,7 @@ #include "zebra/zebra_mpls.h" #include "zebra/debug.h" #include "zebra/zebra_errors.h" +#include "zebra/zebra_router.h" /* communicate the withdrawal of a connected address */ static void connected_withdraw(struct connected *ifc) @@ -207,6 +208,7 @@ void connected_up(struct interface *ifp, struct connected *ifc) }; struct zebra_vrf *zvrf; uint32_t metric; + uint32_t flags = 0; zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id); if (!zvrf) { @@ -251,11 +253,22 @@ void connected_up(struct interface *ifp, struct connected *ifc) metric = (ifc->metric < (uint32_t)METRIC_MAX) ? ifc->metric : ifp->metric; - rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0); - rib_add(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, - 0, 0, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0); + /* + * Since we are hand creating the connected routes + * in our main routing table, *if* we are working + * in an offloaded environment then we need to + * pretend like the route is offloaded so everything + * else will work + */ + if (zrouter.asic_offloaded) + flags |= ZEBRA_FLAG_OFFLOADED; + + rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0, + flags, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0); + + rib_add(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0, + flags, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0); /* Schedule LSP forwarding entries for processing, if appropriate. */ if (zvrf->vrf->vrf_id == VRF_DEFAULT) { diff --git a/zebra/main.c b/zebra/main.c index ced29e1a25..55fd3244cb 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -83,6 +83,8 @@ uint32_t nl_rcvbufsize = 4194304; #endif /* HAVE_NETLINK */ #define OPTION_V6_RR_SEMANTICS 2000 +#define OPTION_ASIC_OFFLOAD 2001 + /* Command line options. */ const struct option longopts[] = { {"batch", no_argument, NULL, 'b'}, @@ -92,6 +94,7 @@ const struct option longopts[] = { {"retain", no_argument, NULL, 'r'}, {"vrfdefaultname", required_argument, NULL, 'o'}, {"graceful_restart", required_argument, NULL, 'K'}, + {"asic-offload", optional_argument, NULL, OPTION_ASIC_OFFLOAD}, #ifdef HAVE_NETLINK {"vrfwnetns", no_argument, NULL, 'n'}, {"nl-bufsize", required_argument, NULL, 's'}, @@ -281,6 +284,8 @@ int main(int argc, char **argv) char *vrf_default_name_configured = NULL; struct sockaddr_storage dummy; socklen_t dummylen; + bool asic_offload = false; + bool notify_on_ack = true; graceful_restart = 0; vrf_configure_backend(VRF_BACKEND_VRF_LITE); @@ -301,6 +306,7 @@ int main(int argc, char **argv) " -r, --retain When program terminates, retain added route by zebra.\n" " -o, --vrfdefaultname Set default VRF name.\n" " -K, --graceful_restart Graceful restart at the kernel level, timer in seconds for expiration\n" + " -A, --asic-offload FRR is interacting with an asic underneath the linux kernel\n" #ifdef HAVE_NETLINK " -n, --vrfwnetns Use NetNS as VRF backend\n" " -s, --nl-bufsize Set netlink receive buffer size\n" @@ -366,6 +372,13 @@ int main(int argc, char **argv) case OPTION_V6_RR_SEMANTICS: v6_rr_semantics = true; break; + case OPTION_ASIC_OFFLOAD: + if (!strcmp(optarg, "notify_on_offload")) + notify_on_ack = false; + if (!strcmp(optarg, "notify_on_ack")) + notify_on_ack = true; + asic_offload = true; + break; #endif /* HAVE_NETLINK */ default: frr_help_exit(1); @@ -376,7 +389,7 @@ int main(int argc, char **argv) zrouter.master = frr_init(); /* Zebra related initialize. */ - zebra_router_init(); + zebra_router_init(asic_offload, notify_on_ack); zserv_init(); rib_init(); zebra_if_init(); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index ef51989a0c..3402edf467 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -642,7 +642,9 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, selfroute = is_selfroute(rtm->rtm_protocol); - if (!startup && selfroute && h->nlmsg_type == RTM_NEWROUTE) { + if (!startup && selfroute + && h->nlmsg_type == RTM_NEWROUTE + && !zrouter.asic_offloaded) { if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("Route type: %d Received that we think we have originated, ignoring", rtm->rtm_protocol); @@ -672,6 +674,8 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, flags |= ZEBRA_FLAG_TRAPPED; if (rtm->rtm_flags & RTM_F_OFFLOAD) flags |= ZEBRA_FLAG_OFFLOADED; + if (rtm->rtm_flags & RTM_F_OFFLOAD_FAILED) + flags |= ZEBRA_FLAG_OFFLOAD_FAILED; /* Route which inserted by Zebra. */ if (selfroute) { @@ -3179,10 +3183,14 @@ ssize_t netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx, void *data, update_flags = dplane_ctx_mac_get_update_flags(ctx); if (update_flags & DPLANE_MAC_REMOTE) { flags |= NTF_SELF; - if (dplane_ctx_mac_is_sticky(ctx)) + if (dplane_ctx_mac_is_sticky(ctx)) { + /* NUD_NOARP prevents the entry from expiring */ + state |= NUD_NOARP; + /* sticky the entry from moving */ flags |= NTF_STICKY; - else + } else { flags |= NTF_EXT_LEARNED; + } /* if it was static-local previously we need to clear the * notify flags on replace with remote */ diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 18017c9700..1d68019909 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -742,7 +742,8 @@ static int nhg_notify(uint16_t type, uint16_t instance, uint32_t id, static int route_notify_internal(const struct prefix *p, int type, uint16_t instance, vrf_id_t vrf_id, uint32_t table_id, - enum zapi_route_notify_owner note) + enum zapi_route_notify_owner note, + afi_t afi, safi_t safi) { struct zserv *client; struct stream *s; @@ -778,16 +779,21 @@ static int route_notify_internal(const struct prefix *p, int type, stream_putl(s, table_id); + /* Encode AFI, SAFI in the message */ + stream_putc(s, afi); + stream_putc(s, safi); + stream_putw_at(s, 0, stream_get_endp(s)); return zserv_send_message(client, s); } int zsend_route_notify_owner(struct route_entry *re, const struct prefix *p, - enum zapi_route_notify_owner note) + enum zapi_route_notify_owner note, + afi_t afi, safi_t safi) { return (route_notify_internal(p, re->type, re->instance, re->vrf_id, - re->table, note)); + re->table, note, afi, safi)); } /* @@ -801,7 +807,19 @@ int zsend_route_notify_owner_ctx(const struct zebra_dplane_ctx *ctx, dplane_ctx_get_instance(ctx), dplane_ctx_get_vrf(ctx), dplane_ctx_get_table(ctx), - note)); + note, + dplane_ctx_get_afi(ctx), + dplane_ctx_get_safi(ctx))); +} + +static void zread_route_notify_request(ZAPI_HANDLER_ARGS) +{ + uint8_t notify; + + STREAM_GETC(msg, notify); + client->notify_owner = notify; +stream_failure: + return; } void zsend_rule_notify_owner(const struct zebra_dplane_ctx *ctx, @@ -3275,6 +3293,7 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_NEIGH_DISCOVER] = zread_neigh_discover, [ZEBRA_NHG_ADD] = zread_nhg_add, [ZEBRA_NHG_DEL] = zread_nhg_del, + [ZEBRA_ROUTE_NOTIFY_REQUEST] = zread_route_notify_request, }; /* diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h index 9f23a313bf..efc52059b6 100644 --- a/zebra/zapi_msg.h +++ b/zebra/zapi_msg.h @@ -77,7 +77,8 @@ extern int zsend_interface_link_params(struct zserv *zclient, extern int zsend_pw_update(struct zserv *client, struct zebra_pw *pw); extern int zsend_route_notify_owner(struct route_entry *re, const struct prefix *p, - enum zapi_route_notify_owner note); + enum zapi_route_notify_owner note, + afi_t afi, safi_t safi); extern int zsend_route_notify_owner_ctx(const struct zebra_dplane_ctx *ctx, enum zapi_route_notify_owner note); diff --git a/zebra/zebra_nb_config.c b/zebra/zebra_nb_config.c index df95770307..ea2e20ed3b 100644 --- a/zebra/zebra_nb_config.c +++ b/zebra/zebra_nb_config.c @@ -1550,12 +1550,14 @@ int lib_route_map_entry_set_action_source_v4_modify( if (pif != NULL) break; } - if (pif == NULL) { - snprintf(args->errmsg, args->errmsg_len, - "is not a local address: %s", - yang_dnode_get_string(args->dnode, NULL)); - return NB_ERR_VALIDATION; - } + /* + * On startup the local address *may* not have come up + * yet. We need to allow startup configuration of + * set src or we are fudged. Log it for future fun + */ + if (pif == NULL) + zlog_warn("set src %pI4 is not a local address", + &p.u.prefix4); return NB_OK; case NB_EV_PREPARE: case NB_EV_ABORT: @@ -1618,12 +1620,14 @@ int lib_route_map_entry_set_action_source_v6_modify( if (pif != NULL) break; } - if (pif == NULL) { - snprintf(args->errmsg, args->errmsg_len, - "is not a local adddress: %s", - yang_dnode_get_string(args->dnode, NULL)); - return NB_ERR_VALIDATION; - } + /* + * On startup the local address *may* not have come up + * yet. We need to allow startup configuration of + * set src or we are fudged. Log it for future fun + */ + if (pif == NULL) + zlog_warn("set src %pI6 is not a local address", + &p.u.prefix6); return NB_OK; case NB_EV_PREPARE: case NB_EV_ABORT: diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index e76ecc85a6..569b23573c 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -481,7 +481,8 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re, * know that they've lost */ if (old && (old != re) && (old->type != re->type)) - zsend_route_notify_owner(old, p, ZAPI_ROUTE_BETTER_ADMIN_WON); + zsend_route_notify_owner(old, p, ZAPI_ROUTE_BETTER_ADMIN_WON, + info->afi, info->safi); /* Update fib selection */ dest->selected_fib = re; @@ -1748,6 +1749,7 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) uint32_t seq; rib_dest_t *dest; bool fib_changed = false; + struct rib_table_info *info; zvrf = vrf_info_lookup(dplane_ctx_get_vrf(ctx)); vrf = vrf_lookup_by_id(dplane_ctx_get_vrf(ctx)); @@ -1767,6 +1769,7 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) dest = rib_dest_from_rnode(rn); srcdest_rnode_prefixes(rn, &dest_pfx, &src_pfx); + info = srcdest_rnode_table_info(rn); op = dplane_ctx_get_op(ctx); status = dplane_ctx_get_status(ctx); @@ -1818,8 +1821,12 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) "%s(%u):%pFX Stale dplane result for re %p", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), dest_pfx, re); - } else - UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED); + } else { + if (!zrouter.asic_offloaded || + (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED) || + CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOAD_FAILED))) + UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED); + } } if (old_re) { @@ -1896,8 +1903,23 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) zvrf->installs++; /* Notify route owner */ - zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_INSTALLED); - + if (zebra_router_notify_on_ack()) + zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_INSTALLED); + else { + if (re) { + if (CHECK_FLAG(re->flags, + ZEBRA_FLAG_OFFLOADED)) + zsend_route_notify_owner_ctx( + ctx, + ZAPI_ROUTE_INSTALLED); + if (CHECK_FLAG( + re->flags, + ZEBRA_FLAG_OFFLOAD_FAILED)) + zsend_route_notify_owner_ctx( + ctx, + ZAPI_ROUTE_FAIL_INSTALL); + } + } } else { if (re) { SET_FLAG(re->status, ROUTE_ENTRY_FAILED); @@ -1906,7 +1928,8 @@ static void rib_process_result(struct zebra_dplane_ctx *ctx) SET_FLAG(old_re->status, ROUTE_ENTRY_FAILED); if (re) zsend_route_notify_owner(re, dest_pfx, - ZAPI_ROUTE_FAIL_INSTALL); + ZAPI_ROUTE_FAIL_INSTALL, + info->afi, info->safi); zlog_warn("%s(%u:%u):%pFX: Route install failed", VRF_LOGNAME(vrf), dplane_ctx_get_vrf(ctx), @@ -2063,7 +2086,8 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) } /* Ensure we clear the QUEUED flag */ - UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED); + if (!zrouter.asic_offloaded) + UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED); /* Is this a notification that ... matters? We mostly care about * the route that is currently selected for installation; we may also diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index 294f2c17ff..7b0a1e3d9c 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -64,19 +64,17 @@ static void zebra_route_map_set_delay_timer(uint32_t value); * Match function return 1 if match is success else return 0 */ static enum route_map_cmd_result_t -route_match_tag(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_tag(void *rule, const struct prefix *prefix, void *object) { route_tag_t *tag; struct nh_rmap_obj *nh_data; - if (type == RMAP_ZEBRA) { - tag = rule; - nh_data = object; + tag = rule; + nh_data = object; + + if (nh_data->tag == *tag) + return RMAP_MATCH; - if (nh_data->tag == *tag) - return RMAP_MATCH; - } return RMAP_NOMATCH; } @@ -92,25 +90,23 @@ static const struct route_map_rule_cmd route_match_tag_cmd = { /* `match interface IFNAME' */ /* Match function return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_interface(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_interface(void *rule, const struct prefix *prefix, void *object) { struct nh_rmap_obj *nh_data; char *ifname = rule; ifindex_t ifindex; - if (type == RMAP_ZEBRA) { - if (strcasecmp(ifname, "any") == 0) - return RMAP_MATCH; - nh_data = object; - if (!nh_data || !nh_data->nexthop) - return RMAP_NOMATCH; - ifindex = ifname2ifindex(ifname, nh_data->vrf_id); - if (ifindex == 0) - return RMAP_NOMATCH; - if (nh_data->nexthop->ifindex == ifindex) - return RMAP_MATCH; - } + if (strcasecmp(ifname, "any") == 0) + return RMAP_MATCH; + nh_data = object; + if (!nh_data || !nh_data->nexthop) + return RMAP_NOMATCH; + ifindex = ifname2ifindex(ifname, nh_data->vrf_id); + if (ifindex == 0) + return RMAP_NOMATCH; + if (nh_data->nexthop->ifindex == ifindex) + return RMAP_MATCH; + return RMAP_NOMATCH; } @@ -938,40 +934,35 @@ DEFPY_YANG (show_ipv6_protocol_nht, /* Match function return 1 if match is success else return zero. */ static enum route_map_cmd_result_t -route_match_ip_next_hop(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_next_hop(void *rule, const struct prefix *prefix, void *object) { struct access_list *alist; struct nh_rmap_obj *nh_data; struct prefix_ipv4 p; - if (type == RMAP_ZEBRA) { - nh_data = object; - if (!nh_data) - return RMAP_NOMATCH; - - switch (nh_data->nexthop->type) { - case NEXTHOP_TYPE_IFINDEX: - /* Interface routes can't match ip next-hop */ - return RMAP_NOMATCH; - case NEXTHOP_TYPE_IPV4_IFINDEX: - case NEXTHOP_TYPE_IPV4: - p.family = AF_INET; - p.prefix = nh_data->nexthop->gate.ipv4; - p.prefixlen = IPV4_MAX_BITLEN; - break; - default: - return RMAP_NOMATCH; - } - alist = access_list_lookup(AFI_IP, (char *)rule); - if (alist == NULL) - return RMAP_NOMATCH; + nh_data = object; + if (!nh_data) + return RMAP_NOMATCH; - return (access_list_apply(alist, &p) == FILTER_DENY - ? RMAP_NOMATCH - : RMAP_MATCH); + switch (nh_data->nexthop->type) { + case NEXTHOP_TYPE_IFINDEX: + /* Interface routes can't match ip next-hop */ + return RMAP_NOMATCH; + case NEXTHOP_TYPE_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4: + p.family = AF_INET; + p.prefix = nh_data->nexthop->gate.ipv4; + p.prefixlen = IPV4_MAX_BITLEN; + break; + default: + return RMAP_NOMATCH; } - return RMAP_NOMATCH; + alist = access_list_lookup(AFI_IP, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; + + return (access_list_apply(alist, &p) == FILTER_DENY ? RMAP_NOMATCH + : RMAP_MATCH); } /* Route map `ip next-hop' match statement. `arg' should be @@ -999,39 +990,35 @@ static const struct route_map_rule_cmd route_match_ip_next_hop_cmd = { static enum route_map_cmd_result_t route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { struct prefix_list *plist; struct nh_rmap_obj *nh_data; struct prefix_ipv4 p; - if (type == RMAP_ZEBRA) { - nh_data = (struct nh_rmap_obj *)object; - if (!nh_data) - return RMAP_NOMATCH; - - switch (nh_data->nexthop->type) { - case NEXTHOP_TYPE_IFINDEX: - /* Interface routes can't match ip next-hop */ - return RMAP_NOMATCH; - case NEXTHOP_TYPE_IPV4_IFINDEX: - case NEXTHOP_TYPE_IPV4: - p.family = AF_INET; - p.prefix = nh_data->nexthop->gate.ipv4; - p.prefixlen = IPV4_MAX_BITLEN; - break; - default: - return RMAP_NOMATCH; - } - plist = prefix_list_lookup(AFI_IP, (char *)rule); - if (plist == NULL) - return RMAP_NOMATCH; + nh_data = (struct nh_rmap_obj *)object; + if (!nh_data) + return RMAP_NOMATCH; - return (prefix_list_apply(plist, &p) == PREFIX_DENY - ? RMAP_NOMATCH - : RMAP_MATCH); + switch (nh_data->nexthop->type) { + case NEXTHOP_TYPE_IFINDEX: + /* Interface routes can't match ip next-hop */ + return RMAP_NOMATCH; + case NEXTHOP_TYPE_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4: + p.family = AF_INET; + p.prefix = nh_data->nexthop->gate.ipv4; + p.prefixlen = IPV4_MAX_BITLEN; + break; + default: + return RMAP_NOMATCH; } - return RMAP_NOMATCH; + plist = prefix_list_lookup(AFI_IP, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; + + return (prefix_list_apply(plist, &p) == PREFIX_DENY ? RMAP_NOMATCH + : RMAP_MATCH); } static void *route_match_ip_next_hop_prefix_list_compile(const char *arg) @@ -1058,34 +1045,28 @@ static const struct route_map_rule_cmd zero. */ static enum route_map_cmd_result_t route_match_address(afi_t afi, void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { struct access_list *alist; - if (type == RMAP_ZEBRA) { - alist = access_list_lookup(afi, (char *)rule); - if (alist == NULL) - return RMAP_NOMATCH; + alist = access_list_lookup(afi, (char *)rule); + if (alist == NULL) + return RMAP_NOMATCH; - return (access_list_apply(alist, prefix) == FILTER_DENY - ? RMAP_NOMATCH - : RMAP_MATCH); - } - return RMAP_NOMATCH; + return (access_list_apply(alist, prefix) == FILTER_DENY ? RMAP_NOMATCH + : RMAP_MATCH); } static enum route_map_cmd_result_t -route_match_ip_address(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ip_address(void *rule, const struct prefix *prefix, void *object) { - return route_match_address(AFI_IP, rule, prefix, type, object); + return route_match_address(AFI_IP, rule, prefix, object); } static enum route_map_cmd_result_t -route_match_ipv6_address(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) +route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object) { - return route_match_address(AFI_IP6, rule, prefix, type, object); + return route_match_address(AFI_IP6, rule, prefix, object); } /* Route map `ip address' match statement. `arg' should be @@ -1121,28 +1102,23 @@ static const struct route_map_rule_cmd route_match_ipv6_address_cmd = { static enum route_map_cmd_result_t route_match_address_prefix_list(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object, afi_t afi) + void *object, afi_t afi) { struct prefix_list *plist; - if (type == RMAP_ZEBRA) { - plist = prefix_list_lookup(afi, (char *)rule); - if (plist == NULL) - return RMAP_NOMATCH; + plist = prefix_list_lookup(afi, (char *)rule); + if (plist == NULL) + return RMAP_NOMATCH; - return (prefix_list_apply(plist, prefix) == PREFIX_DENY - ? RMAP_NOMATCH - : RMAP_MATCH); - } - return RMAP_NOMATCH; + return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH + : RMAP_MATCH); } static enum route_map_cmd_result_t route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { - return (route_match_address_prefix_list(rule, prefix, type, object, - AFI_IP)); + return (route_match_address_prefix_list(rule, prefix, object, AFI_IP)); } static void *route_match_address_prefix_list_compile(const char *arg) @@ -1165,10 +1141,9 @@ static const struct route_map_rule_cmd static enum route_map_cmd_result_t route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { - return (route_match_address_prefix_list(rule, prefix, type, object, - AFI_IP6)); + return (route_match_address_prefix_list(rule, prefix, object, AFI_IP6)); } static const struct route_map_rule_cmd @@ -1183,11 +1158,11 @@ static const struct route_map_rule_cmd static enum route_map_cmd_result_t route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { struct nh_rmap_obj *nh_data; - if (type == RMAP_ZEBRA && prefix->family == AF_INET6) { + if (prefix->family == AF_INET6) { nh_data = (struct nh_rmap_obj *)object; if (!nh_data) return RMAP_NOMATCH; @@ -1195,6 +1170,7 @@ route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix, if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE) return RMAP_MATCH; } + return RMAP_NOMATCH; } @@ -1220,15 +1196,11 @@ static const struct route_map_rule_cmd static enum route_map_cmd_result_t route_match_address_prefix_len(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { uint32_t *prefixlen = (uint32_t *)rule; - if (type == RMAP_ZEBRA) { - return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH - : RMAP_NOMATCH); - } - return RMAP_NOMATCH; + return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH); } static void *route_match_address_prefix_len_compile(const char *arg) @@ -1277,34 +1249,30 @@ static const struct route_map_rule_cmd static enum route_map_cmd_result_t route_match_ip_nexthop_prefix_len(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { uint32_t *prefixlen = (uint32_t *)rule; struct nh_rmap_obj *nh_data; struct prefix_ipv4 p; - if (type == RMAP_ZEBRA) { - nh_data = (struct nh_rmap_obj *)object; - if (!nh_data || !nh_data->nexthop) - return RMAP_NOMATCH; + nh_data = (struct nh_rmap_obj *)object; + if (!nh_data || !nh_data->nexthop) + return RMAP_NOMATCH; - switch (nh_data->nexthop->type) { - case NEXTHOP_TYPE_IFINDEX: - /* Interface routes can't match ip next-hop */ - return RMAP_NOMATCH; - case NEXTHOP_TYPE_IPV4_IFINDEX: - case NEXTHOP_TYPE_IPV4: - p.family = AF_INET; - p.prefix = nh_data->nexthop->gate.ipv4; - p.prefixlen = IPV4_MAX_BITLEN; - break; - default: - return RMAP_NOMATCH; - } - return ((p.prefixlen == *prefixlen) ? RMAP_MATCH - : RMAP_NOMATCH); + switch (nh_data->nexthop->type) { + case NEXTHOP_TYPE_IFINDEX: + /* Interface routes can't match ip next-hop */ + return RMAP_NOMATCH; + case NEXTHOP_TYPE_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV4: + p.family = AF_INET; + p.prefix = nh_data->nexthop->gate.ipv4; + p.prefixlen = IPV4_MAX_BITLEN; + break; + default: + return RMAP_NOMATCH; } - return RMAP_NOMATCH; + return ((p.prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH); } static const struct route_map_rule_cmd @@ -1319,11 +1287,11 @@ static const struct route_map_rule_cmd static enum route_map_cmd_result_t route_match_ip_next_hop_type(void *rule, const struct prefix *prefix, - route_map_object_t type, void *object) + void *object) { struct nh_rmap_obj *nh_data; - if (type == RMAP_ZEBRA && prefix->family == AF_INET) { + if (prefix->family == AF_INET) { nh_data = (struct nh_rmap_obj *)object; if (!nh_data) return RMAP_NOMATCH; @@ -1331,6 +1299,7 @@ route_match_ip_next_hop_type(void *rule, const struct prefix *prefix, if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE) return RMAP_MATCH; } + return RMAP_NOMATCH; } @@ -1355,21 +1324,17 @@ static const struct route_map_rule_cmd /* `match source-protocol PROTOCOL' */ static enum route_map_cmd_result_t -route_match_source_protocol(void *rule, const struct prefix *p, - route_map_object_t type, void *object) +route_match_source_protocol(void *rule, const struct prefix *p, void *object) { uint32_t *rib_type = (uint32_t *)rule; struct nh_rmap_obj *nh_data; - if (type == RMAP_ZEBRA) { - nh_data = (struct nh_rmap_obj *)object; - if (!nh_data) - return RMAP_NOMATCH; + nh_data = (struct nh_rmap_obj *)object; + if (!nh_data) + return RMAP_NOMATCH; - return ((nh_data->source_protocol == *rib_type) ? RMAP_MATCH - : RMAP_NOMATCH); - } - return RMAP_NOMATCH; + return ((nh_data->source_protocol == *rib_type) ? RMAP_MATCH + : RMAP_NOMATCH); } static void *route_match_source_protocol_compile(const char *arg) @@ -1399,15 +1364,11 @@ static const struct route_map_rule_cmd route_match_source_protocol_cmd = { /* `source-instance` */ static enum route_map_cmd_result_t -route_match_source_instance(void *rule, const struct prefix *p, - route_map_object_t type, void *object) +route_match_source_instance(void *rule, const struct prefix *p, void *object) { uint8_t *instance = (uint8_t *)rule; struct nh_rmap_obj *nh_data; - if (type != RMAP_ZEBRA) - return RMAP_NOMATCH; - nh_data = (struct nh_rmap_obj *)object; if (!nh_data) return RMAP_NOMATCH; @@ -1444,15 +1405,13 @@ static const struct route_map_rule_cmd route_match_source_instance_cmd = { /* Set src. */ static enum route_map_cmd_result_t -route_set_src(void *rule, const struct prefix *prefix, route_map_object_t type, - void *object) +route_set_src(void *rule, const struct prefix *prefix, void *object) { struct nh_rmap_obj *nh_data; - if (type == RMAP_ZEBRA) { - nh_data = (struct nh_rmap_obj *)object; - nh_data->nexthop->rmap_src = *(union g_addr *)rule; - } + nh_data = (struct nh_rmap_obj *)object; + nh_data->nexthop->rmap_src = *(union g_addr *)rule; + return RMAP_OKAY; } @@ -1738,7 +1697,7 @@ zebra_route_map_check(int family, int rib_type, uint8_t instance, if (!rmap && PROTO_RM_NAME(zvrf, family, ZEBRA_ROUTE_MAX)) rmap = PROTO_RM_MAP(zvrf, family, ZEBRA_ROUTE_MAX); if (rmap) { - ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); + ret = route_map_apply(rmap, p, &nh_obj); } return (ret); @@ -1782,7 +1741,7 @@ zebra_import_table_route_map_check(int family, int re_type, uint8_t instance, if (re_type >= 0 && re_type < ZEBRA_ROUTE_MAX) rmap = route_map_lookup_by_name(rmap_name); if (rmap) { - ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); + ret = route_map_apply(rmap, p, &nh_obj); } return (ret); @@ -1810,7 +1769,7 @@ route_map_result_t zebra_nht_route_map_check(afi_t afi, int client_proto, if (!rmap && NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX)) rmap = NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX); if (rmap) - ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); + ret = route_map_apply(rmap, p, &nh_obj); return ret; } diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c index fc4390f7f8..249ec38a69 100644 --- a/zebra/zebra_router.c +++ b/zebra/zebra_router.c @@ -257,7 +257,12 @@ void zebra_router_terminate(void) hash_free(zrouter.iptable_hash); } -void zebra_router_init(void) +bool zebra_router_notify_on_ack(void) +{ + return !zrouter.asic_offloaded || zrouter.notify_on_ack; +} + +void zebra_router_init(bool asic_offload, bool notify_on_ack) { zrouter.sequence_num = 0; @@ -291,5 +296,6 @@ void zebra_router_init(void) hash_create_size(8, zebra_nhg_id_key, zebra_nhg_hash_id_equal, "Zebra Router Nexthop Groups ID index"); - zrouter.asic_offloaded = false; + zrouter.asic_offloaded = asic_offload; + zrouter.notify_on_ack = notify_on_ack; } diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h index 8651a01e9f..08c5fcaf8d 100644 --- a/zebra/zebra_router.h +++ b/zebra/zebra_router.h @@ -210,13 +210,14 @@ struct zebra_router { * Does the underlying system provide an asic offload */ bool asic_offloaded; + bool notify_on_ack; }; #define GRACEFUL_RESTART_TIME 60 extern struct zebra_router zrouter; -extern void zebra_router_init(void); +extern void zebra_router_init(bool asic_offload, bool notify_on_ack); extern void zebra_router_cleanup(void); extern void zebra_router_terminate(void); @@ -255,6 +256,8 @@ extern void multicast_mode_ipv4_set(enum multicast_mode mode); extern enum multicast_mode multicast_mode_ipv4_get(void); +extern bool zebra_router_notify_on_ack(void); + /* zebra_northbound.c */ extern const struct frr_yang_module_info frr_zebra_info; diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index ab7d2845e7..ea7baa2565 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -204,12 +204,16 @@ static char re_status_output_char(const struct route_entry *re, star_p = true; } + if (zrouter.asic_offloaded && + CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED)) + return 'q'; + if (zrouter.asic_offloaded && CHECK_FLAG(re->flags, ZEBRA_FLAG_TRAPPED)) return 't'; if (zrouter.asic_offloaded - && !CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED)) + && CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOAD_FAILED)) return 'o'; if (star_p) @@ -870,6 +874,9 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, if (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED)) json_object_boolean_true_add(json_route, "offloaded"); + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOAD_FAILED)) + json_object_boolean_false_add(json_route, "offloaded"); + if (re->tag) json_object_int_add(json_route, "tag", re->tag); @@ -2005,6 +2012,8 @@ static void vty_show_ip_route_summary(struct vty *vty, #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1) uint32_t rib_cnt[ZEBRA_ROUTE_TOTAL + 1]; uint32_t fib_cnt[ZEBRA_ROUTE_TOTAL + 1]; + uint32_t offload_cnt[ZEBRA_ROUTE_TOTAL + 1]; + uint32_t trap_cnt[ZEBRA_ROUTE_TOTAL + 1]; uint32_t i; uint32_t is_ibgp; json_object *json_route_summary = NULL; @@ -2012,6 +2021,8 @@ static void vty_show_ip_route_summary(struct vty *vty, memset(&rib_cnt, 0, sizeof(rib_cnt)); memset(&fib_cnt, 0, sizeof(fib_cnt)); + memset(&offload_cnt, 0, sizeof(offload_cnt)); + memset(&trap_cnt, 0, sizeof(trap_cnt)); if (use_json) { json_route_summary = json_object_new_object(); @@ -2039,6 +2050,20 @@ static void vty_show_ip_route_summary(struct vty *vty, else fib_cnt[re->type]++; } + + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_TRAPPED)) { + if (is_ibgp) + trap_cnt[ZEBRA_ROUTE_IBGP]++; + else + trap_cnt[re->type]++; + } + + if (CHECK_FLAG(re->flags, ZEBRA_FLAG_OFFLOADED)) { + if (is_ibgp) + offload_cnt[ZEBRA_ROUTE_IBGP]++; + else + offload_cnt[re->type]++; + } } if (!use_json) @@ -2062,6 +2087,13 @@ static void vty_show_ip_route_summary(struct vty *vty, json_object_int_add( json_route_ebgp, "rib", rib_cnt[ZEBRA_ROUTE_BGP]); + json_object_int_add( + json_route_ebgp, "fibOffLoaded", + offload_cnt[ZEBRA_ROUTE_BGP]); + json_object_int_add( + json_route_ebgp, "fibTrapped", + trap_cnt[ZEBRA_ROUTE_BGP]); + json_object_string_add(json_route_ebgp, "type", "ebgp"); json_object_array_add(json_route_routes, @@ -2076,6 +2108,12 @@ static void vty_show_ip_route_summary(struct vty *vty, json_object_int_add( json_route_ibgp, "rib", rib_cnt[ZEBRA_ROUTE_IBGP]); + json_object_int_add( + json_route_ibgp, "fibOffLoaded", + offload_cnt[ZEBRA_ROUTE_IBGP]); + json_object_int_add( + json_route_ibgp, "fibTrapped", + trap_cnt[ZEBRA_ROUTE_IBGP]); json_object_string_add(json_route_ibgp, "type", "ibgp"); json_object_array_add(json_route_routes, @@ -2099,6 +2137,13 @@ static void vty_show_ip_route_summary(struct vty *vty, "fib", fib_cnt[i]); json_object_int_add(json_route_type, "rib", rib_cnt[i]); + + json_object_int_add(json_route_type, + "fibOffLoaded", + offload_cnt[i]); + json_object_int_add(json_route_type, + "fibTrapped", + trap_cnt[i]); json_object_string_add( json_route_type, "type", zebra_route_string(i)); |
