]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_updgrp_packet.c
bgpd: Adding BGP GR Global & Per Neighbour FSM changes
[mirror_frr.git] / bgpd / bgp_updgrp_packet.c
index 688abae0e41ae36033ee56f23311467885b0fc27..39eb065288fc4a3f4a384014a458fb43acc6ae4c 100644 (file)
@@ -391,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);
@@ -401,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
@@ -439,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)) {
@@ -543,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)) {
@@ -733,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 =
@@ -883,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);
        }