]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_updgrp_packet.c
Merge pull request #5717 from pguibert6WIND/flowspec_issue_redistribute
[mirror_frr.git] / bgpd / bgp_updgrp_packet.c
index ca6bb5ab82ea86e4d9dfc5ce8365f7baa77108a6..39eb065288fc4a3f4a384014a458fb43acc6ae4c 100644 (file)
 /********************
  * 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;