X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=bgpd%2Fbgp_updgrp_packet.c;h=39eb065288fc4a3f4a384014a458fb43acc6ae4c;hb=b6cac82ed9643f8bd6c0644205f5673e4ac8efa0;hp=ca6bb5ab82ea86e4d9dfc5ce8365f7baa77108a6;hpb=d8e331eb0e66991b9c280c6f004eb2f8da4c2e28;p=mirror_frr.git diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c index ca6bb5ab8..39eb06528 100644 --- a/bgpd/bgp_updgrp_packet.c +++ b/bgpd/bgp_updgrp_packet.c @@ -65,12 +65,11 @@ /******************** * PUBLIC FUNCTIONS ********************/ -struct bpacket *bpacket_alloc() +struct bpacket *bpacket_alloc(void) { struct bpacket *pkt; - pkt = (struct bpacket *)XCALLOC(MTYPE_BGP_PACKET, - sizeof(struct bpacket)); + pkt = XCALLOC(MTYPE_BGP_PACKET, sizeof(struct bpacket)); return pkt; } @@ -392,6 +391,7 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt, struct peer *peer; char buf[BUFSIZ]; char buf2[BUFSIZ]; + struct bgp_filter *filter; s = stream_dup(pkt->buffer); peer = PAF_PEER(paf); @@ -402,6 +402,8 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt, afi_t nhafi; int route_map_sets_nh; nhlen = stream_getc_from(s, vec->offset); + filter = &peer->filter[paf->afi][paf->safi]; + if (peer_cap_enhe(peer, paf->afi, paf->safi)) nhafi = AFI_IP6; else @@ -440,25 +442,25 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt, mod_v4nh = &v4nh; /* - * If route-map has set the nexthop, that is always - * used; if it is - * specified as peer-address, the peering address is - * picked up. - * Otherwise, if NH is unavailable from attribute, the - * peering addr - * is picked up; the "NH unavailable" case also covers - * next-hop-self - * and some other scenarios -- see - * subgroup_announce_check(). In - * all other cases, use the nexthop carried in the - * attribute unless - * it is EBGP non-multiaccess and there is no - * next-hop-unchanged setting. + * If route-map has set the nexthop, that is normally + * used; if it is specified as peer-address, the peering + * address is picked up. Otherwise, if NH is unavailable + * from attribute, the peering addr is picked up; the + * "NH unavailable" case also covers next-hop-self and + * some other scenarios - see subgroup_announce_check(). + * In all other cases, use the nexthop carried in the + * attribute unless it is EBGP non-multiaccess and there + * is no next-hop-unchanged setting or the peer is EBGP + * and the route-map that changed the next-hop value + * was applied inbound rather than outbound. Updates to + * an EBGP peer should only modify the next-hop if it + * was set in an outbound route-map to that peer. * Note: It is assumed route-map cannot set the nexthop - * to an - * invalid value. + * to an invalid value. */ - if (route_map_sets_nh) { + if (route_map_sets_nh + && ((peer->sort != BGP_PEER_EBGP) + || ROUTE_MAP_OUT(filter))) { if (CHECK_FLAG( vec->flags, BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS)) { @@ -544,7 +546,15 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt, stream_get_from(&v6nhglobal, s, offset_nhglobal, IPV6_MAX_BYTELEN); - if (route_map_sets_nh) { + + /* + * Updates to an EBGP peer should only modify the + * next-hop if it was set in an outbound route-map + * to that peer. + */ + if (route_map_sets_nh + && ((peer->sort != BGP_PEER_EBGP) + || ROUTE_MAP_OUT(filter))) { if (CHECK_FLAG( vec->flags, BPKT_ATTRVEC_FLAGS_RMAP_NH_PEER_ADDRESS)) { @@ -555,9 +565,9 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt, mod_v6nhg = &peer->nexthop.v6_global; gnh_modified = 1; } else if ( - peer->sort == BGP_PEER_EBGP - && !CHECK_FLAG( - vec->flags, + (peer->sort == BGP_PEER_EBGP) + && (!bgp_multiaccess_check_v6(v6nhglobal, peer)) + && !CHECK_FLAG(vec->flags, BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED) && !peer_af_flag_check( peer, nhafi, paf->safi, @@ -665,11 +675,11 @@ int subgroup_packets_to_build(struct update_subgroup *subgrp) if (!subgrp) return 0; - adv = BGP_ADV_FIFO_HEAD(&subgrp->sync->withdraw); + adv = bgp_adv_fifo_first(&subgrp->sync->withdraw); if (adv) return 1; - adv = BGP_ADV_FIFO_HEAD(&subgrp->sync->update); + adv = bgp_adv_fifo_first(&subgrp->sync->update); if (adv) return 1; @@ -726,7 +736,7 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp) addpath_encode = bgp_addpath_encode_tx(peer, afi, safi); addpath_overhead = addpath_encode ? BGP_ADDPATH_ID_LEN : 0; - adv = BGP_ADV_FIFO_HEAD(&subgrp->sync->update); + adv = bgp_adv_fifo_first(&subgrp->sync->update); while (adv) { assert(adv->rn); rn = adv->rn; @@ -734,6 +744,22 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp) addpath_tx_id = adj->addpath_tx_id; path = adv->pathi; + /* Check if we need to add a prefix to the packet if + * maximum-prefix-out is set for the peer. + */ + if (CHECK_FLAG(peer->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_OUT) + && subgrp->scount >= peer->pmax_out[afi][safi]) { + if (BGP_DEBUG(update, UPDATE_OUT) + || BGP_DEBUG(update, UPDATE_PREFIX)) { + zlog_debug( + "%s reached maximum prefix to be send (%" PRIu32 + ")", + peer->host, peer->pmax_out[afi][safi]); + } + goto next; + } + space_remaining = STREAM_CONCAT_REMAIN(s, snlri, STREAM_SIZE(s)) - BGP_MAX_PACKET_SIZE_OVERFLOW; space_needed = @@ -884,7 +910,7 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp) subgrp->scount++; adj->attr = bgp_attr_intern(adv->baa->attr); - +next: adv = bgp_advertise_clean_subgroup(subgrp, adj); } @@ -967,7 +993,7 @@ struct bpacket *subgroup_withdraw_packet(struct update_subgroup *subgrp) addpath_encode = bgp_addpath_encode_tx(peer, afi, safi); addpath_overhead = addpath_encode ? BGP_ADDPATH_ID_LEN : 0; - while ((adv = BGP_ADV_FIFO_HEAD(&subgrp->sync->withdraw)) != NULL) { + while ((adv = bgp_adv_fifo_first(&subgrp->sync->withdraw)) != NULL) { assert(adv->rn); adj = adv->adj; rn = adv->rn;