]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_route.c
Merge pull request #5844 from qlyoung/fix-zebra-gr-unnecessary-malloc
[mirror_frr.git] / bgpd / bgp_route.c
index 21d737fb32847ac291f003b783d252954f90301b..1cd0bbe5786226cfbf58101ed9692bbe2a4755d4 100644 (file)
 #include "workqueue.h"
 #include "queue.h"
 #include "memory.h"
+#include "srv6.h"
 #include "lib/json.h"
 #include "lib_errors.h"
-
+#include "zclient.h"
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_table.h"
 #include "bgpd/bgp_route.h"
@@ -89,7 +90,7 @@
 /* Extern from bgp_dump.c */
 extern const char *bgp_origin_str[];
 extern const char *bgp_origin_long_str[];
-
+const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json);
 /* PMSI strings. */
 #define PMSI_TNLTYPE_STR_NO_INFO "No info"
 #define PMSI_TNLTYPE_STR_DEFAULT PMSI_TNLTYPE_STR_NO_INFO
@@ -233,8 +234,6 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
        if ((*extra)->bgp_fs_pbr)
                list_delete(&((*extra)->bgp_fs_pbr));
        XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
-
-       *extra = NULL;
 }
 
 /* Get bgp_path_info extra information for the given bgp_path_info, lazy
@@ -295,6 +294,87 @@ struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path)
        return path;
 }
 
+/* This function sets flag BGP_NODE_SELECT_DEFER based on condition */
+static int bgp_node_set_defer_flag(struct bgp_node *rn, bool delete)
+{
+       struct peer *peer;
+       struct bgp_path_info *old_pi, *nextpi;
+       bool set_flag = 0;
+       struct bgp *bgp = NULL;
+       struct bgp_table *table = NULL;
+       afi_t afi = 0;
+       safi_t safi = 0;
+       char buf[PREFIX2STR_BUFFER];
+
+       /* If the flag BGP_NODE_SELECT_DEFER is set and new path is added
+        * then the route selection is deferred
+        */
+       if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER) && (!delete))
+               return 0;
+
+       if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED)) {
+               if (BGP_DEBUG(update, UPDATE_OUT)) {
+                       prefix2str(&rn->p, buf, PREFIX2STR_BUFFER);
+                       zlog_debug(
+                               "Route %s is in workqueue and being processed, not deferred.",
+                               buf);
+               }
+               return 0;
+       }
+
+       table = bgp_node_table(rn);
+       if (table) {
+               bgp = table->bgp;
+               afi = table->afi;
+               safi = table->safi;
+       }
+
+       for (old_pi = bgp_node_get_bgp_path_info(rn);
+            (old_pi != NULL) && (nextpi = old_pi->next, 1); old_pi = nextpi) {
+               if (CHECK_FLAG(old_pi->flags, BGP_PATH_SELECTED))
+                       continue;
+
+               /* Route selection is deferred if there is a stale path which
+                * which indicates peer is in restart mode
+                */
+               if (CHECK_FLAG(old_pi->flags, BGP_PATH_STALE)
+                   && (old_pi->sub_type == BGP_ROUTE_NORMAL)) {
+                       set_flag = 1;
+               } else {
+                       /* If the peer is graceful restart capable and peer is
+                        * restarting mode, set the flag BGP_NODE_SELECT_DEFER
+                        */
+                       peer = old_pi->peer;
+                       if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)
+                           && BGP_PEER_RESTARTING_MODE(peer)
+                           && (old_pi
+                               && old_pi->sub_type == BGP_ROUTE_NORMAL)) {
+                               set_flag = 1;
+                       }
+               }
+               if (set_flag)
+                       break;
+       }
+
+       /* Set the flag BGP_NODE_SELECT_DEFER if route selection deferral timer
+        * is active
+        */
+       if (set_flag && table) {
+               if (bgp && (bgp->gr_info[afi][safi].t_select_deferral)) {
+                       SET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
+                       prefix2str(&rn->p, buf, PREFIX2STR_BUFFER);
+                       if (rn->rt_node == NULL)
+                               rn->rt_node = listnode_add(
+                                       bgp->gr_info[afi][safi].route_list, rn);
+                       if (BGP_DEBUG(update, UPDATE_OUT))
+                               zlog_debug("DEFER route %s, rn %p, node %p",
+                                          buf, rn, rn->rt_node);
+                       return 0;
+               }
+       }
+       return -1;
+}
+
 void bgp_path_info_add(struct bgp_node *rn, struct bgp_path_info *pi)
 {
        struct bgp_path_info *top;
@@ -310,6 +390,7 @@ void bgp_path_info_add(struct bgp_node *rn, struct bgp_path_info *pi)
        bgp_path_info_lock(pi);
        bgp_lock_node(rn);
        peer_lock(pi->peer); /* bgp_path_info peer reference */
+       bgp_node_set_defer_flag(rn, false);
 }
 
 /* Do the actual removal of info from RIB, for use by bgp_process
@@ -420,7 +501,7 @@ static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
        if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
                return attr->med;
        else {
-               if (bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST))
+               if (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
                        return BGP_MED_MAX;
                else
                        return 0;
@@ -666,11 +747,11 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
        }
 
        /* 4. AS path length check. */
-       if (!bgp_flag_check(bgp, BGP_FLAG_ASPATH_IGNORE)) {
+       if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) {
                int exist_hops = aspath_count_hops(existattr->aspath);
                int exist_confeds = aspath_count_confeds(existattr->aspath);
 
-               if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_CONFED)) {
+               if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) {
                        int aspath_hops;
 
                        aspath_hops = aspath_count_hops(newattr->aspath);
@@ -751,8 +832,8 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
                           && aspath_count_hops(newattr->aspath) == 0
                           && aspath_count_hops(existattr->aspath) == 0);
 
-       if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED)
-           || (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED) && confed_as_route)
+       if (CHECK_FLAG(bgp->flags, BGP_FLAG_ALWAYS_COMPARE_MED)
+           || (CHECK_FLAG(bgp->flags, BGP_FLAG_MED_CONFED) && confed_as_route)
            || aspath_cmp_left(newattr->aspath, existattr->aspath)
            || aspath_cmp_left_confed(newattr->aspath, existattr->aspath)
            || internal_as_route) {
@@ -833,8 +914,8 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
           pair (newm, existm) with the cluster list length. Prefer the
           path with smaller cluster list length.                       */
        if (newm == existm) {
-               if (peer_sort(new->peer) == BGP_PEER_IBGP
-                   && peer_sort(exist->peer) == BGP_PEER_IBGP
+               if (peer_sort_lookup(new->peer) == BGP_PEER_IBGP
+                   && peer_sort_lookup(exist->peer) == BGP_PEER_IBGP
                    && (mpath_cfg == NULL
                        || CHECK_FLAG(
                                   mpath_cfg->ibgp_flags,
@@ -897,8 +978,8 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
                                zlog_debug(
                                        "%s: %s and %s cannot be multipath, one has a label while the other does not",
                                        pfx_buf, new_buf, exist_buf);
-               } else if (bgp_flag_check(bgp,
-                                         BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
+               } else if (CHECK_FLAG(bgp->flags,
+                                     BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
 
                        /*
                         * For the two paths, all comparison steps till IGP
@@ -960,7 +1041,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
           first (the oldest one).  This step minimizes route-flap, since a
           newer path won't displace an older one, even if it was the
           preferred route based on the additional decision criteria below.  */
-       if (!bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID)
+       if (!CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_ROUTER_ID)
            && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) {
                if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) {
                        *reason = bgp_path_selection_older;
@@ -1454,8 +1535,8 @@ void bgp_attr_add_gshut_community(struct attr *attr)
 static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr)
 {
        if (family == AF_INET) {
-               attr->nexthop.s_addr = 0;
-               attr->mp_nexthop_global_in.s_addr = 0;
+               attr->nexthop.s_addr = INADDR_ANY;
+               attr->mp_nexthop_global_in.s_addr = INADDR_ANY;
        }
        if (family == AF_INET6)
                memset(&attr->mp_nexthop_global, 0, IPV6_MAX_BYTELEN);
@@ -1681,7 +1762,8 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
                           check
                           is already done.  So there is noting to do. */
                        /* no bgp client-to-client reflection check. */
-                       if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
+                       if (CHECK_FLAG(bgp->flags,
+                                      BGP_FLAG_NO_CLIENT_TO_CLIENT))
                                if (CHECK_FLAG(peer->af_flags[afi][safi],
                                               PEER_FLAG_REFLECTOR_CLIENT))
                                        return 0;
@@ -1813,8 +1895,8 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
                 * of the reflected IBGP routes unless explicitly allowed.
                 */
                if ((from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
-                   && !bgp_flag_check(bgp,
-                                      BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
+                   && !CHECK_FLAG(bgp->flags,
+                                  BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
                        dummy_attr = *attr;
                        rmap_path.attr = &dummy_attr;
                }
@@ -1864,7 +1946,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
                if (aspath_check_as_sets(attr->aspath))
                        return 0;
 
-       if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
+       if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
                if (peer->sort == BGP_PEER_IBGP
                    || peer->sort == BGP_PEER_CONFED) {
                        attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
@@ -1973,6 +2055,30 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
        return 1;
 }
 
+static int bgp_route_select_timer_expire(struct thread *thread)
+{
+       struct afi_safi_info *info;
+       afi_t afi;
+       safi_t safi;
+       struct bgp *bgp;
+
+       info = THREAD_ARG(thread);
+       afi = info->afi;
+       safi = info->safi;
+       bgp = info->bgp;
+
+       if (BGP_DEBUG(update, UPDATE_OUT))
+               zlog_debug("afi %d, safi %d : route select timer expired", afi,
+                          safi);
+
+       bgp->gr_info[afi][safi].t_route_select = NULL;
+
+       XFREE(MTYPE_TMP, info);
+
+       /* Best path selection */
+       return bgp_best_path_select_defer(bgp, afi, safi);
+}
+
 void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
                        struct bgp_maxpaths_cfg *mpath_cfg,
                        struct bgp_path_info_pair *result, afi_t afi,
@@ -2000,7 +2106,7 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
 
        /* bgp deterministic-med */
        new_select = NULL;
-       if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) {
+       if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
 
                /* Clear BGP_PATH_DMED_SELECTED for all paths */
                for (pi1 = bgp_node_get_bgp_path_info(rn); pi1;
@@ -2107,7 +2213,7 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
                                continue;
                        }
 
-               if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
+               if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
                    && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
                        bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
                        if (debug)
@@ -2340,14 +2446,14 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
        char pfx_buf[PREFIX2STR_BUFFER];
        int debug = 0;
 
-       if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS)) {
+       if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) {
                if (rn)
                        debug = bgp_debug_bestpath(&rn->p);
                if (debug) {
                        prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
                        zlog_debug(
-                            "%s: bgp delete in progress, ignoring event, p=%s",
-                            __func__, pfx_buf);
+                               "%s: bgp delete in progress, ignoring event, p=%s",
+                               __func__, pfx_buf);
                }
                return;
        }
@@ -2376,6 +2482,15 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
                           afi2str(afi), safi2str(safi));
        }
 
+       /* The best path calculation for the route is deferred if
+        * BGP_NODE_SELECT_DEFER is set
+        */
+       if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
+               if (BGP_DEBUG(update, UPDATE_OUT))
+                       zlog_debug("SELECT_DEFER falg set for route %p", rn);
+               return;
+       }
+
        /* Best path selection. */
        bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
                           afi, safi);
@@ -2603,6 +2718,65 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn,
        return;
 }
 
+/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
+int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
+{
+       struct bgp_node *rn;
+       int cnt = 0;
+       struct afi_safi_info *thread_info;
+       struct listnode *node = NULL, *nnode = NULL;
+
+       if (bgp->gr_info[afi][safi].t_route_select)
+               BGP_TIMER_OFF(bgp->gr_info[afi][safi].t_route_select);
+
+       if (BGP_DEBUG(update, UPDATE_OUT)) {
+               zlog_debug("%s: processing route for %s : cnt %d", __func__,
+                          get_afi_safi_str(afi, safi, false),
+                          listcount(bgp->gr_info[afi][safi].route_list));
+       }
+
+       /* Process the route list */
+       node = listhead(bgp->gr_info[afi][safi].route_list);
+       while (node) {
+               rn = listgetdata(node);
+               nnode = node->next;
+               list_delete_node(bgp->gr_info[afi][safi].route_list, node);
+               rn->rt_node = NULL;
+
+               if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
+                       UNSET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
+                       bgp_process_main_one(bgp, rn, afi, safi);
+                       cnt++;
+                       if (cnt >= BGP_MAX_BEST_ROUTE_SELECT)
+                               break;
+               }
+               node = nnode;
+       }
+
+       /* Send EOR message when all routes are processed */
+       if (list_isempty(bgp->gr_info[afi][safi].route_list)) {
+               bgp_send_delayed_eor(bgp);
+               /* Send route processing complete message to RIB */
+               bgp_zebra_update(afi, safi, bgp->vrf_id,
+                                ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
+               return 0;
+       }
+
+       thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
+
+       thread_info->afi = afi;
+       thread_info->safi = safi;
+       thread_info->bgp = bgp;
+
+       /* If there are more routes to be processed, start the
+        * selection timer
+        */
+       thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
+                       BGP_ROUTE_SELECT_DELAY,
+                       &bgp->gr_info[afi][safi].t_route_select);
+       return 0;
+}
+
 static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
 {
        struct bgp_process_queue *pqnode = data;
@@ -2681,6 +2855,16 @@ void bgp_process(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi)
        if (CHECK_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED))
                return;
 
+       /* If the flag BGP_NODE_SELECT_DEFER is set, do not add route to
+        * the workqueue
+        */
+       if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
+               if (BGP_DEBUG(update, UPDATE_OUT))
+                       zlog_debug("BGP_NODE_SELECT_DEFER set for route %p",
+                                  rn);
+               return;
+       }
+
        if (wq == NULL)
                return;
 
@@ -2844,13 +3028,38 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi,
 void bgp_rib_remove(struct bgp_node *rn, struct bgp_path_info *pi,
                    struct peer *peer, afi_t afi, safi_t safi)
 {
+
+       struct bgp *bgp = NULL;
+       bool delete_route = false;
+
        bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi, safi);
 
-       if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
+       if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
                bgp_path_info_delete(rn, pi); /* keep historical info */
 
-       hook_call(bgp_process, peer->bgp, afi, safi, rn, peer, true);
+               /* If the selected path is removed, reset BGP_NODE_SELECT_DEFER
+                * flag
+                */
+               if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
+                       delete_route = true;
+               else if (bgp_node_set_defer_flag(rn, true) < 0)
+                       delete_route = true;
+               if (delete_route) {
+                       if (CHECK_FLAG(rn->flags, BGP_NODE_SELECT_DEFER)) {
+                               UNSET_FLAG(rn->flags, BGP_NODE_SELECT_DEFER);
+                               bgp = pi->peer->bgp;
+                               if ((rn->rt_node)
+                                   && (bgp->gr_info[afi][safi].route_list)) {
+                                       list_delete_node(bgp->gr_info[afi][safi]
+                                                                .route_list,
+                                                        rn->rt_node);
+                                       rn->rt_node = NULL;
+                               }
+                       }
+               }
+       }
 
+       hook_call(bgp_process, peer->bgp, afi, safi, rn, peer, true);
        bgp_process(peer->bgp, rn, afi, safi);
 }
 
@@ -2992,10 +3201,9 @@ static int bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
 
        /* If NEXT_HOP is present, validate it. */
        if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) {
-               if (attr->nexthop.s_addr == 0
+               if (attr->nexthop.s_addr == INADDR_ANY
                    || IPV4_CLASS_DE(ntohl(attr->nexthop.s_addr))
-                   || bgp_nexthop_self(bgp, afi, type, stype,
-                       attr, rn))
+                   || bgp_nexthop_self(bgp, afi, type, stype, attr, rn))
                        return 1;
        }
 
@@ -3008,11 +3216,11 @@ static int bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
                switch (attr->mp_nexthop_len) {
                case BGP_ATTR_NHLEN_IPV4:
                case BGP_ATTR_NHLEN_VPNV4:
-                       ret = (attr->mp_nexthop_global_in.s_addr == 0
-                              || IPV4_CLASS_DE(ntohl(
-                                         attr->mp_nexthop_global_in.s_addr))
-                              || bgp_nexthop_self(bgp, afi, type, stype,
-                                                  attr, rn));
+                       ret = (attr->mp_nexthop_global_in.s_addr == INADDR_ANY
+                              || IPV4_CLASS_DE(
+                                      ntohl(attr->mp_nexthop_global_in.s_addr))
+                              || bgp_nexthop_self(bgp, afi, type, stype, attr,
+                                                  rn));
                        break;
 
                case BGP_ATTR_NHLEN_IPV6_GLOBAL:
@@ -3211,10 +3419,9 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
 
                        /* If graceful-shutdown is configured then add the GSHUT
                         * community to all paths received from eBGP peers */
-               } else if (bgp_flag_check(peer->bgp,
-                                         BGP_FLAG_GRACEFUL_SHUTDOWN)) {
+               } else if (CHECK_FLAG(peer->bgp->flags,
+                                     BGP_FLAG_GRACEFUL_SHUTDOWN))
                        bgp_attr_add_gshut_community(&new_attr);
-               }
        }
 
        if (pi) {
@@ -3302,6 +3509,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
                                if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
                                        bgp_path_info_unset_flag(
                                                rn, pi, BGP_PATH_STALE);
+                                       bgp_node_set_defer_flag(rn, false);
                                        bgp_process(bgp, rn, afi, safi);
                                }
                        }
@@ -3337,8 +3545,10 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
                }
 
                /* graceful restart STALE flag unset. */
-               if (CHECK_FLAG(pi->flags, BGP_PATH_STALE))
+               if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) {
                        bgp_path_info_unset_flag(rn, pi, BGP_PATH_STALE);
+                       bgp_node_set_defer_flag(rn, false);
+               }
 
                /* The attribute is changed. */
                bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED);
@@ -3431,6 +3641,22 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
                                bgp_set_valid_label(&extra->label[0]);
                }
 
+               /* Update SRv6 SID */
+               if (attr->srv6_l3vpn) {
+                       extra = bgp_path_info_extra_get(pi);
+                       if (sid_diff(&extra->sid[0], &attr->srv6_l3vpn->sid)) {
+                               sid_copy(&extra->sid[0],
+                                        &attr->srv6_l3vpn->sid);
+                               extra->num_sids = 1;
+                       }
+               } else if (attr->srv6_vpn) {
+                       extra = bgp_path_info_extra_get(pi);
+                       if (sid_diff(&extra->sid[0], &attr->srv6_vpn->sid)) {
+                               sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
+                               extra->num_sids = 1;
+                       }
+               }
+
 #if ENABLE_BGP_VNC
                if ((afi == AFI_IP || afi == AFI_IP6)
                    && (safi == SAFI_UNICAST)) {
@@ -3481,8 +3707,8 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
                            && peer->ttl == BGP_DEFAULT_TTL
                            && !CHECK_FLAG(peer->flags,
                                           PEER_FLAG_DISABLE_CONNECTED_CHECK)
-                           && !bgp_flag_check(
-                                      bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
+                           && !CHECK_FLAG(bgp->flags,
+                                          BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
                                connected = 1;
                        else
                                connected = 0;
@@ -3610,6 +3836,18 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
                        bgp_set_valid_label(&extra->label[0]);
        }
 
+       /* Update SRv6 SID */
+       if (safi == SAFI_MPLS_VPN) {
+               extra = bgp_path_info_extra_get(new);
+               if (attr->srv6_l3vpn) {
+                       sid_copy(&extra->sid[0], &attr->srv6_l3vpn->sid);
+                       extra->num_sids = 1;
+               } else if (attr->srv6_vpn) {
+                       sid_copy(&extra->sid[0], &attr->srv6_vpn->sid);
+                       extra->num_sids = 1;
+               }
+       }
+
        /* Update Overlay Index */
        if (afi == AFI_L2VPN) {
                overlay_index_update(new->attr,
@@ -3624,7 +3862,8 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
                    && peer->ttl == BGP_DEFAULT_TTL
                    && !CHECK_FLAG(peer->flags,
                                   PEER_FLAG_DISABLE_CONNECTED_CHECK)
-                   && !bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
+                   && !CHECK_FLAG(bgp->flags,
+                                  BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
                        connected = 1;
                else
                        connected = 0;
@@ -4515,7 +4754,8 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
                        if (pnt + BGP_ADDPATH_ID_LEN >= lim)
                                return BGP_NLRI_PARSE_ERROR_PACKET_OVERFLOW;
 
-                       addpath_id = ntohl(*((uint32_t *)pnt));
+                       memcpy(&addpath_id, pnt, BGP_ADDPATH_ID_LEN);
+                       addpath_id = ntohl(addpath_id);
                        pnt += BGP_ADDPATH_ID_LEN;
                }
 
@@ -4714,13 +4954,13 @@ void bgp_static_update(struct bgp *bgp, struct prefix *p,
                        return;
                }
 
-               if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
+               if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
                        bgp_attr_add_gshut_community(&attr_tmp);
 
                attr_new = bgp_attr_intern(&attr_tmp);
        } else {
 
-               if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
+               if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
                        bgp_attr_add_gshut_community(&attr);
 
                attr_new = bgp_attr_intern(&attr);
@@ -4734,7 +4974,7 @@ void bgp_static_update(struct bgp *bgp, struct prefix *p,
        if (pi) {
                if (attrhash_cmp(pi->attr, attr_new)
                    && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)
-                   && !bgp_flag_check(bgp, BGP_FLAG_FORCE_STATIC_PROCESS)) {
+                   && !CHECK_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS)) {
                        bgp_unlock_node(rn);
                        bgp_attr_unintern(&attr_new);
                        aspath_unintern(&attr.aspath);
@@ -4779,7 +5019,7 @@ void bgp_static_update(struct bgp *bgp, struct prefix *p,
 #endif
 
                        /* Nexthop reachability check. */
-                       if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
+                       if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
                            && (safi == SAFI_UNICAST
                                || safi == SAFI_LABELED_UNICAST)) {
 
@@ -4838,7 +5078,7 @@ void bgp_static_update(struct bgp *bgp, struct prefix *p,
        new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self,
                        attr_new, rn);
        /* Nexthop reachability check. */
-       if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
+       if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)
            && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) {
                if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0))
                        bgp_path_info_set_flag(rn, new, BGP_PATH_VALID);
@@ -5225,7 +5465,6 @@ static int bgp_static_set(struct vty *vty, const char *negate,
                                      bgp_static->rmap.name);
                                route_map_counter_decrement(
                                        bgp_static->rmap.map);
-                               bgp_static->rmap.name = NULL;
                                bgp_static->rmap.map = NULL;
                                bgp_static->valid = 0;
                        }
@@ -5236,7 +5475,7 @@ static int bgp_static_set(struct vty *vty, const char *negate,
                        bgp_static->backdoor = backdoor;
                        bgp_static->valid = 0;
                        bgp_static->igpmetric = 0;
-                       bgp_static->igpnexthop.s_addr = 0;
+                       bgp_static->igpnexthop.s_addr = INADDR_ANY;
                        bgp_static->label_index = label_index;
 
                        if (rmap) {
@@ -5358,7 +5597,7 @@ void bgp_static_redo_import_check(struct bgp *bgp)
        struct bgp_static *bgp_static;
 
        /* Use this flag to force reprocessing of the route */
-       bgp_flag_set(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
+       SET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
        FOREACH_AFI_SAFI (afi, safi) {
                for (rn = bgp_table_top(bgp->route[afi][safi]); rn;
                     rn = bgp_route_next(rn)) {
@@ -5385,7 +5624,7 @@ void bgp_static_redo_import_check(struct bgp *bgp)
                        }
                }
        }
-       bgp_flag_unset(bgp, BGP_FLAG_FORCE_STATIC_PROCESS);
+       UNSET_FLAG(bgp->flags, BGP_FLAG_FORCE_STATIC_PROCESS);
 }
 
 static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
@@ -5398,8 +5637,8 @@ static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
        /* Do not install the aggregate route if BGP is in the
         * process of termination.
         */
-       if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS) ||
-           (bgp->peer_self == NULL))
+       if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
+           || (bgp->peer_self == NULL))
                return;
 
        table = bgp->rib[afi][safi];
@@ -5527,7 +5766,7 @@ int bgp_static_set_safi(afi_t afi, safi_t safi, struct vty *vty,
                bgp_static->backdoor = 0;
                bgp_static->valid = 0;
                bgp_static->igpmetric = 0;
-               bgp_static->igpnexthop.s_addr = 0;
+               bgp_static->igpnexthop.s_addr = INADDR_ANY;
                bgp_static->label = label;
                bgp_static->prd = prd;
 
@@ -5647,7 +5886,6 @@ static int bgp_table_map_set(struct vty *vty, afi_t afi, safi_t safi,
        } else {
                XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
                route_map_counter_decrement(rmap->map);
-               rmap->name = NULL;
                rmap->map = NULL;
        }
 
@@ -5666,7 +5904,6 @@ static int bgp_table_map_unset(struct vty *vty, afi_t afi, safi_t safi,
        rmap = &bgp->table_map[afi][safi];
        XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
        route_map_counter_decrement(rmap->map);
-       rmap->name = NULL;
        rmap->map = NULL;
 
        if (bgp_fibupd_safi(safi))
@@ -5910,8 +6147,8 @@ void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
        /* If the bgp instance is being deleted or self peer is deleted
         * then do not create aggregate route
         */
-       if (bgp_flag_check(bgp, BGP_FLAG_DELETE_IN_PROGRESS) ||
-          (bgp->peer_self == NULL))
+       if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)
+           || (bgp->peer_self == NULL))
                return;
 
        /* ORIGIN attribute: If at least one route among routes that are
@@ -6033,6 +6270,9 @@ void bgp_aggregate_route(struct bgp *bgp, struct prefix *p,
        else if (aggregate->egp_origin_count > 0)
                origin = BGP_ORIGIN_EGP;
 
+       if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
+               origin = aggregate->origin;
+
        if (aggregate->as_set) {
                if (aggregate->aspath)
                        /* Retrieve aggregate route's as-path.
@@ -6197,6 +6437,9 @@ static void bgp_add_route_to_aggregate(struct bgp *bgp, struct prefix *aggr_p,
        else if (aggregate->egp_origin_count > 0)
                origin = BGP_ORIGIN_EGP;
 
+       if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
+               origin = aggregate->origin;
+
        if (aggregate->as_set) {
                /* Compute aggregate route's as-path.
                 */
@@ -6328,6 +6571,9 @@ static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
        else if (aggregate->egp_origin_count > 0)
                origin = BGP_ORIGIN_EGP;
 
+       if (aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
+               origin = aggregate->origin;
+
        if (aggregate->as_set) {
                /* Retrieve aggregate route's as-path.
                 */
@@ -6423,6 +6669,19 @@ void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p,
 #define AGGREGATE_AS_SET       1
 #define AGGREGATE_AS_UNSET     0
 
+static const char *bgp_origin2str(uint8_t origin)
+{
+       switch (origin) {
+       case BGP_ORIGIN_IGP:
+               return "igp";
+       case BGP_ORIGIN_EGP:
+               return "egp";
+       case BGP_ORIGIN_INCOMPLETE:
+               return "incomplete";
+       }
+       return "n/a";
+}
+
 static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
                               afi_t afi, safi_t safi)
 {
@@ -6516,8 +6775,9 @@ static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str,
 }
 
 static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
-                            safi_t safi, const char *rmap, uint8_t summary_only,
-                            uint8_t as_set)
+                            safi_t safi, const char *rmap,
+                            uint8_t summary_only, uint8_t as_set,
+                            uint8_t origin)
 {
        VTY_DECLVAR_CONTEXT(bgp, bgp);
        int ret;
@@ -6581,6 +6841,12 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
 
        aggregate->as_set = as_set_new;
        aggregate->safi = safi;
+       /* Override ORIGIN attribute if defined.
+        * E.g.: Cisco and Juniper set ORIGIN for aggregated address
+        * to IGP which is not what rfc4271 says.
+        * This enables the same behavior, optionally.
+        */
+       aggregate->origin = origin;
 
        if (rmap) {
                XFREE(MTYPE_ROUTE_MAP_NAME, aggregate->rmap.name);
@@ -6600,7 +6866,7 @@ static int bgp_aggregate_set(struct vty *vty, const char *prefix_str, afi_t afi,
 
 DEFUN (aggregate_address,
        aggregate_address_cmd,
-       "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
+       "aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
        "Configure BGP aggregate entries\n"
        "Aggregate prefix\n"
        "Generate AS set path information\n"
@@ -6608,12 +6874,17 @@ DEFUN (aggregate_address,
        "Filter more specific routes from updates\n"
        "Generate AS set path information\n"
        "Apply route map to aggregate network\n"
-       "Name of route map\n")
+       "Name of route map\n"
+       "BGP origin code\n"
+       "Remote EGP\n"
+       "Local IGP\n"
+       "Unknown heritage\n")
 {
        int idx = 0;
        argv_find(argv, argc, "A.B.C.D/M", &idx);
        char *prefix = argv[idx]->arg;
        char *rmap = NULL;
+       uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
        int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
                                                           : AGGREGATE_AS_UNSET;
        idx = 0;
@@ -6626,13 +6897,23 @@ DEFUN (aggregate_address,
        if (idx)
                rmap = argv[idx]->arg;
 
-       return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty),
-                                rmap, summary_only, as_set);
+       idx = 0;
+       if (argv_find(argv, argc, "origin", &idx)) {
+               if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
+                       origin = BGP_ORIGIN_IGP;
+               if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
+                       origin = BGP_ORIGIN_EGP;
+               if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
+                       origin = BGP_ORIGIN_INCOMPLETE;
+       }
+
+       return bgp_aggregate_set(vty, prefix, AFI_IP, bgp_node_safi(vty), rmap,
+                                summary_only, as_set, origin);
 }
 
 DEFUN (aggregate_address_mask,
        aggregate_address_mask_cmd,
-       "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
+       "aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
        "Configure BGP aggregate entries\n"
        "Aggregate address\n"
        "Aggregate mask\n"
@@ -6641,7 +6922,11 @@ DEFUN (aggregate_address_mask,
        "Filter more specific routes from updates\n"
        "Generate AS set path information\n"
        "Apply route map to aggregate network\n"
-       "Name of route map\n")
+       "Name of route map\n"
+       "BGP origin code\n"
+       "Remote EGP\n"
+       "Local IGP\n"
+       "Unknown heritage\n")
 {
        int idx = 0;
        argv_find(argv, argc, "A.B.C.D", &idx);
@@ -6649,6 +6934,7 @@ DEFUN (aggregate_address_mask,
        char *mask = argv[idx + 1]->arg;
        bool rmap_found;
        char *rmap = NULL;
+       uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
        int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
                                                           : AGGREGATE_AS_UNSET;
        idx = 0;
@@ -6668,13 +6954,23 @@ DEFUN (aggregate_address_mask,
                return CMD_WARNING_CONFIG_FAILED;
        }
 
+       idx = 0;
+       if (argv_find(argv, argc, "origin", &idx)) {
+               if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
+                       origin = BGP_ORIGIN_IGP;
+               if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
+                       origin = BGP_ORIGIN_EGP;
+               if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
+                       origin = BGP_ORIGIN_INCOMPLETE;
+       }
+
        return bgp_aggregate_set(vty, prefix_str, AFI_IP, bgp_node_safi(vty),
-                                rmap, summary_only, as_set);
+                                rmap, summary_only, as_set, origin);
 }
 
 DEFUN (no_aggregate_address,
        no_aggregate_address_cmd,
-       "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
+       "no aggregate-address A.B.C.D/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
        NO_STR
        "Configure BGP aggregate entries\n"
        "Aggregate prefix\n"
@@ -6683,7 +6979,11 @@ DEFUN (no_aggregate_address,
        "Filter more specific routes from updates\n"
        "Generate AS set path information\n"
        "Apply route map to aggregate network\n"
-       "Name of route map\n")
+       "Name of route map\n"
+       "BGP origin code\n"
+       "Remote EGP\n"
+       "Local IGP\n"
+       "Unknown heritage\n")
 {
        int idx = 0;
        argv_find(argv, argc, "A.B.C.D/M", &idx);
@@ -6693,7 +6993,7 @@ DEFUN (no_aggregate_address,
 
 DEFUN (no_aggregate_address_mask,
        no_aggregate_address_mask_cmd,
-       "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
+       "no aggregate-address A.B.C.D A.B.C.D [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
        NO_STR
        "Configure BGP aggregate entries\n"
        "Aggregate address\n"
@@ -6703,7 +7003,11 @@ DEFUN (no_aggregate_address_mask,
        "Filter more specific routes from updates\n"
        "Generate AS set path information\n"
        "Apply route map to aggregate network\n"
-       "Name of route map\n")
+       "Name of route map\n"
+       "BGP origin code\n"
+       "Remote EGP\n"
+       "Local IGP\n"
+       "Unknown heritage\n")
 {
        int idx = 0;
        argv_find(argv, argc, "A.B.C.D", &idx);
@@ -6723,7 +7027,7 @@ DEFUN (no_aggregate_address_mask,
 
 DEFUN (ipv6_aggregate_address,
        ipv6_aggregate_address_cmd,
-       "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
+       "aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
        "Configure BGP aggregate entries\n"
        "Aggregate prefix\n"
        "Generate AS set path information\n"
@@ -6731,13 +7035,18 @@ DEFUN (ipv6_aggregate_address,
        "Filter more specific routes from updates\n"
        "Generate AS set path information\n"
        "Apply route map to aggregate network\n"
-       "Name of route map\n")
+       "Name of route map\n"
+       "BGP origin code\n"
+       "Remote EGP\n"
+       "Local IGP\n"
+       "Unknown heritage\n")
 {
        int idx = 0;
        argv_find(argv, argc, "X:X::X:X/M", &idx);
        char *prefix = argv[idx]->arg;
        char *rmap = NULL;
        bool rmap_found;
+       uint8_t origin = BGP_ORIGIN_UNSPECIFIED;
        int as_set = argv_find(argv, argc, "as-set", &idx) ? AGGREGATE_AS_SET
                                                           : AGGREGATE_AS_UNSET;
 
@@ -6750,13 +7059,23 @@ DEFUN (ipv6_aggregate_address,
        if (rmap_found)
                rmap = argv[idx]->arg;
 
+       idx = 0;
+       if (argv_find(argv, argc, "origin", &idx)) {
+               if (strncmp(argv[idx + 1]->arg, "igp", 2) == 0)
+                       origin = BGP_ORIGIN_IGP;
+               if (strncmp(argv[idx + 1]->arg, "egp", 1) == 0)
+                       origin = BGP_ORIGIN_EGP;
+               if (strncmp(argv[idx + 1]->arg, "incomplete", 2) == 0)
+                       origin = BGP_ORIGIN_INCOMPLETE;
+       }
+
        return bgp_aggregate_set(vty, prefix, AFI_IP6, SAFI_UNICAST, rmap,
-                                sum_only, as_set);
+                                sum_only, as_set, origin);
 }
 
 DEFUN (no_ipv6_aggregate_address,
        no_ipv6_aggregate_address_cmd,
-       "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD]",
+       "no aggregate-address X:X::X:X/M [<as-set [summary-only]|summary-only [as-set]>] [route-map WORD] [origin <egp|igp|incomplete>]",
        NO_STR
        "Configure BGP aggregate entries\n"
        "Aggregate prefix\n"
@@ -6765,7 +7084,11 @@ DEFUN (no_ipv6_aggregate_address,
        "Filter more specific routes from updates\n"
        "Generate AS set path information\n"
        "Apply route map to aggregate network\n"
-       "Name of route map\n")
+       "Name of route map\n"
+       "BGP origin code\n"
+       "Remote EGP\n"
+       "Local IGP\n"
+       "Unknown heritage\n")
 {
        int idx = 0;
        argv_find(argv, argc, "X:X::X:X/M", &idx);
@@ -6865,7 +7188,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
                        }
                }
 
-               if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
+               if (CHECK_FLAG(bgp->flags, BGP_FLAG_GRACEFUL_SHUTDOWN))
                        bgp_attr_add_gshut_community(&attr_new);
 
                bn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi,
@@ -7156,7 +7479,8 @@ static void route_vty_short_status_out(struct vty *vty,
 
 static char *bgp_nexthop_hostname(struct peer *peer, struct attr *attr)
 {
-       if (peer->hostname && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)
+       if (peer->hostname
+           && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)
            && !(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))
                return peer->hostname;
        return NULL;
@@ -7303,7 +7627,7 @@ void route_vty_out(struct vty *vty, struct prefix *p,
                                                 : inet_ntoa(attr->nexthop),
                                vrf_id_str);
        } else if (safi == SAFI_FLOWSPEC) {
-               if (attr->nexthop.s_addr != 0) {
+               if (attr->nexthop.s_addr != INADDR_ANY) {
                        if (json_paths) {
                                json_nexthop_global = json_object_new_object();
 
@@ -8170,7 +8494,7 @@ static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer,
                }
 
                if (peer->hostname
-                   && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
+                   && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
                        if (peer->conf_if)
                                vty_out(vty, " %s(%s)", peer->hostname,
                                        peer->conf_if);
@@ -8207,70 +8531,48 @@ static const char *bgp_path_selection_reason2str(
        switch (reason) {
        case bgp_path_selection_none:
                return "Nothing to Select";
-               break;
        case bgp_path_selection_first:
                return "First path received";
-               break;
        case bgp_path_selection_evpn_sticky_mac:
                return "EVPN Sticky Mac";
-               break;
        case bgp_path_selection_evpn_seq:
                return "EVPN sequence number";
-               break;
        case bgp_path_selection_evpn_lower_ip:
                return "EVPN lower IP";
-               break;
        case bgp_path_selection_weight:
                return "Weight";
-               break;
        case bgp_path_selection_local_pref:
                return "Local Pref";
-               break;
        case bgp_path_selection_local_route:
                return "Local Route";
-               break;
        case bgp_path_selection_confed_as_path:
                return "Confederation based AS Path";
-               break;
        case bgp_path_selection_as_path:
                return "AS Path";
-               break;
        case bgp_path_selection_origin:
                return "Origin";
-               break;
        case bgp_path_selection_med:
                return "MED";
-               break;
        case bgp_path_selection_peer:
                return "Peer Type";
-               break;
        case bgp_path_selection_confed:
                return "Confed Peer Type";
-               break;
        case bgp_path_selection_igp_metric:
                return "IGP Metric";
-               break;
        case bgp_path_selection_older:
                return "Older Path";
-               break;
        case bgp_path_selection_router_id:
                return "Router ID";
-               break;
        case bgp_path_selection_cluster_length:
                return "Cluser length";
-               break;
        case bgp_path_selection_stale:
                return "Path Staleness";
-               break;
        case bgp_path_selection_local_configured:
                return "Locally configured route";
-               break;
        case bgp_path_selection_neighbor_ip:
                return "Neighbor IP";
-               break;
        case bgp_path_selection_default:
                return "Nothing left to compare";
-               break;
        }
        return "Invalid (internal error)";
 }
@@ -8592,8 +8894,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
                } else {
                        if (path->peer->conf_if) {
                                if (path->peer->hostname
-                                   && bgp_flag_check(path->peer->bgp,
-                                                     BGP_FLAG_SHOW_HOSTNAME))
+                                   && CHECK_FLAG(path->peer->bgp->flags,
+                                                 BGP_FLAG_SHOW_HOSTNAME))
                                        vty_out(vty, " from %s(%s)",
                                                path->peer->hostname,
                                                path->peer->conf_if);
@@ -8602,8 +8904,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
                                                path->peer->conf_if);
                        } else {
                                if (path->peer->hostname
-                                   && bgp_flag_check(path->peer->bgp,
-                                                     BGP_FLAG_SHOW_HOSTNAME))
+                                   && CHECK_FLAG(path->peer->bgp->flags,
+                                                 BGP_FLAG_SHOW_HOSTNAME))
                                        vty_out(vty, " from %s(%s)",
                                                path->peer->hostname,
                                                path->peer->host);
@@ -8651,8 +8953,13 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
                } else {
                        if (nexthop_vrfid == VRF_UNKNOWN)
                                vty_out(vty, " vrf ?");
-                       else
-                               vty_out(vty, " vrf %u", nexthop_vrfid);
+                       else {
+                               struct vrf *vrf;
+
+                               vrf = vrf_lookup_by_id(nexthop_vrfid);
+                               vty_out(vty, " vrf %s(%u)",
+                                       VRF_LOGNAME(vrf), nexthop_vrfid);
+                       }
                }
        }
 
@@ -8993,6 +9300,15 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
                        vty_out(vty, "      Remote label: %d\n", label);
        }
 
+       /* Remote SID */
+       if (path->extra && path->extra->num_sids > 0 && safi != SAFI_EVPN) {
+               inet_ntop(AF_INET6, &path->extra->sid, buf, sizeof(buf));
+               if (json_paths)
+                       json_object_string_add(json_path, "remoteSid", buf);
+               else
+                       vty_out(vty, "      Remote SID: %s\n", buf);
+       }
+
        /* Label Index */
        if (attr->label_index != BGP_INVALID_LABEL_INDEX) {
                if (json_paths)
@@ -10111,32 +10427,20 @@ DEFUN (show_ip_bgp_large_community_list,
        "Exact match of the large-communities\n"
        JSON_STR)
 {
-       char *vrf = NULL;
        afi_t afi = AFI_IP6;
        safi_t safi = SAFI_UNICAST;
        int idx = 0;
        bool exact_match = 0;
-
-       if (argv_find(argv, argc, "ip", &idx))
-               afi = AFI_IP;
-       if (argv_find(argv, argc, "view", &idx)
-           || argv_find(argv, argc, "vrf", &idx))
-               vrf = argv[++idx]->arg;
-       if (argv_find(argv, argc, "ipv4", &idx)
-           || argv_find(argv, argc, "ipv6", &idx)) {
-               afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
-               if (argv_find(argv, argc, "unicast", &idx)
-                   || argv_find(argv, argc, "multicast", &idx))
-                       safi = bgp_vty_safi_from_str(argv[idx]->text);
-       }
-
+       struct bgp *bgp = NULL;
        bool uj = use_json(argc, argv);
 
-       struct bgp *bgp = bgp_lookup_by_name(vrf);
-       if (bgp == NULL) {
-               vty_out(vty, "Can't find BGP instance %s\n", vrf);
-               return CMD_WARNING;
-       }
+        if (uj)
+                argc--;
+
+        bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
+                                            &bgp, uj);
+        if (!idx)
+                return CMD_WARNING;
 
        argv_find(argv, argc, "large-community-list", &idx);
 
@@ -10162,32 +10466,20 @@ DEFUN (show_ip_bgp_large_community,
        "Exact match of the large-communities\n"
        JSON_STR)
 {
-       char *vrf = NULL;
        afi_t afi = AFI_IP6;
        safi_t safi = SAFI_UNICAST;
        int idx = 0;
        bool exact_match = 0;
-
-       if (argv_find(argv, argc, "ip", &idx))
-               afi = AFI_IP;
-       if (argv_find(argv, argc, "view", &idx)
-           || argv_find(argv, argc, "vrf", &idx))
-               vrf = argv[++idx]->arg;
-       if (argv_find(argv, argc, "ipv4", &idx)
-           || argv_find(argv, argc, "ipv6", &idx)) {
-               afi = strmatch(argv[idx]->text, "ipv6") ? AFI_IP6 : AFI_IP;
-               if (argv_find(argv, argc, "unicast", &idx)
-                   || argv_find(argv, argc, "multicast", &idx))
-                       safi = bgp_vty_safi_from_str(argv[idx]->text);
-       }
-
+       struct bgp *bgp = NULL;
        bool uj = use_json(argc, argv);
 
-       struct bgp *bgp = bgp_lookup_by_name(vrf);
-       if (bgp == NULL) {
-               vty_out(vty, "Can't find BGP instance %s\n", vrf);
-               return CMD_WARNING;
-       }
+        if (uj)
+                argc--;
+
+        bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
+                                            &bgp, uj);
+        if (!idx)
+                return CMD_WARNING;
 
        if (argv_find(argv, argc, "AA:BB:CC", &idx)) {
                if (argv_find(argv, argc, "exact-match", &idx))
@@ -10493,6 +10785,7 @@ DEFUN (show_ip_bgp_regexp,
        if (argv_find(argv, argc, "REGEX", &idx))
                regstr = argv[idx]->arg;
 
+       assert(regstr);
        return bgp_show_regexp(vty, bgp, (const char *)regstr, afi, safi,
                                 bgp_show_type_regexp, uj);
 }
@@ -11087,7 +11380,7 @@ static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi,
        } else {
 
                if (peer->hostname
-                   && bgp_flag_check(peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) {
+                   && CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHOW_HOSTNAME)) {
                        vty_out(vty, "Prefix counts for %s/%s, %s\n",
                                peer->hostname, peer->host,
                                get_afi_safi_str(afi, safi, false));
@@ -11937,10 +12230,7 @@ static int bgp_distance_set(struct vty *vty, const char *distance_str,
        bdistance->distance = distance;
 
        /* Reset access-list configuration. */
-       if (bdistance->access_list) {
-               XFREE(MTYPE_AS_LIST, bdistance->access_list);
-               bdistance->access_list = NULL;
-       }
+       XFREE(MTYPE_AS_LIST, bdistance->access_list);
        if (access_list_str)
                bdistance->access_list =
                        XSTRDUP(MTYPE_AS_LIST, access_list_str);
@@ -12693,6 +12983,10 @@ void bgp_config_write_network(struct vty *vty, struct bgp *bgp, afi_t afi,
                if (bgp_aggregate->rmap.name)
                        vty_out(vty, " route-map %s", bgp_aggregate->rmap.name);
 
+               if (bgp_aggregate->origin != BGP_ORIGIN_UNSPECIFIED)
+                       vty_out(vty, " origin %s",
+                               bgp_origin2str(bgp_aggregate->origin));
+
                vty_out(vty, "\n");
        }
 }