]> git.proxmox.com Git - mirror_frr.git/blobdiff - bgpd/bgp_route.c
*: auto-convert to SPDX License IDs
[mirror_frr.git] / bgpd / bgp_route.c
index d7ff0e3c0a3c76034ec76c4ef7ca26d1791bf98d..ba19b3bb2a61df62b83e62cb0a84efa14eab125b 100644 (file)
@@ -1,22 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /* BGP routing information
  * Copyright (C) 1996, 97, 98, 99 Kunihiro Ishiguro
  * Copyright (C) 2016 Job Snijders <job@instituut.net>
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * GNU Zebra is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * 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 <zebra.h>
@@ -12058,9 +12043,16 @@ const struct prefix_rd *bgp_rd_from_dest(const struct bgp_dest *dest,
        case SAFI_ENCAP:
        case SAFI_EVPN:
                return (struct prefix_rd *)(bgp_dest_get_prefix(dest));
-       default:
+       case SAFI_UNSPEC:
+       case SAFI_UNICAST:
+       case SAFI_MULTICAST:
+       case SAFI_LABELED_UNICAST:
+       case SAFI_FLOWSPEC:
+       case SAFI_MAX:
                return NULL;
        }
+
+       assert(!"Reached end of function when we were not expecting it");
 }
 
 /* Display specified route of BGP table. */
@@ -13285,7 +13277,8 @@ static void bgp_table_stats_walker(struct thread *t)
        case AFI_L2VPN:
                space = EVPN_ROUTE_PREFIXLEN;
                break;
-       default:
+       case AFI_UNSPEC:
+       case AFI_MAX:
                return;
        }
 
@@ -13540,7 +13533,8 @@ static int bgp_table_stats_single(struct vty *vty, struct bgp *bgp, afi_t afi,
        case AFI_L2VPN:
                bitlen = EVPN_ROUTE_PREFIXLEN;
                break;
-       default:
+       case AFI_UNSPEC:
+       case AFI_MAX:
                break;
        }
 
@@ -13967,16 +13961,17 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
               const char *rmap_name, json_object *json, json_object *json_ar,
               json_object *json_scode, json_object *json_ocode,
               uint16_t show_flags, int *header1, int *header2, char *rd_str,
-              unsigned long *output_count, unsigned long *filtered_count)
+              const struct prefix *match, unsigned long *output_count,
+              unsigned long *filtered_count)
 {
-       struct bgp_adj_in *ain;
-       struct bgp_adj_out *adj;
+       struct bgp_adj_in *ain = NULL;
+       struct bgp_adj_out *adj = NULL;
        struct bgp_dest *dest;
        struct bgp *bgp;
        struct attr attr;
        int ret;
        struct update_subgroup *subgrp;
-       struct peer_af *paf;
+       struct peer_af *paf = NULL;
        bool route_filtered;
        bool detail = CHECK_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
        bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
@@ -13990,6 +13985,98 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
 
        bgp = peer->bgp;
 
+       /* If the user supplied a prefix, look for a matching route instead
+        * of walking the whole table.
+        */
+       if (match) {
+               dest = bgp_node_match(table, match);
+               if (!dest) {
+                       if (!use_json)
+                               vty_out(vty, "Network not in table\n");
+                       return;
+               }
+
+               const struct prefix *rn_p = bgp_dest_get_prefix(dest);
+
+               if (rn_p->prefixlen != match->prefixlen) {
+                       if (!use_json)
+                               vty_out(vty, "Network not in table\n");
+                       bgp_dest_unlock_node(dest);
+                       return;
+               }
+
+               if (type == bgp_show_adj_route_received ||
+                   type == bgp_show_adj_route_filtered) {
+                       for (ain = dest->adj_in; ain; ain = ain->next) {
+                               if (ain->peer == peer) {
+                                       attr = *ain->attr;
+                                       break;
+                               }
+                       }
+                       /* bail out if if adj_out is empty, or
+                        * if the prefix isn't in this peer's
+                        * adj_in
+                        */
+                       if (!ain || ain->peer != peer) {
+                               if (!use_json)
+                                       vty_out(vty, "Network not in table\n");
+                               bgp_dest_unlock_node(dest);
+                               return;
+                       }
+               } else if (type == bgp_show_adj_route_advertised) {
+                       bool peer_found = false;
+
+                       RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out) {
+                               SUBGRP_FOREACH_PEER (adj->subgroup, paf) {
+                                       if (paf->peer == peer && adj->attr) {
+                                               attr = *adj->attr;
+                                               peer_found = true;
+                                               break;
+                                       }
+                               }
+                               if (peer_found)
+                                       break;
+                       }
+                       /* bail out if if adj_out is empty, or
+                        * if the prefix isn't in this peer's
+                        * adj_out
+                        */
+                       if (!paf || !peer_found) {
+                               if (!use_json)
+                                       vty_out(vty, "Network not in table\n");
+                               bgp_dest_unlock_node(dest);
+                               return;
+                       }
+               }
+
+               ret = bgp_output_modifier(peer, rn_p, &attr, afi, safi,
+                                         rmap_name);
+
+               if (ret != RMAP_DENY) {
+                       show_adj_route_header(vty, peer, table, header1,
+                                             header2, json, json_scode,
+                                             json_ocode, wide, detail);
+
+                       if (use_json)
+                               json_net = json_object_new_object();
+
+                       bgp_show_path_info(NULL /* prefix_rd */, dest, vty, bgp,
+                                          afi, safi, json_net,
+                                          BGP_PATH_SHOW_ALL, &display,
+                                          RPKI_NOT_BEING_USED);
+                       if (use_json)
+                               json_object_object_addf(json_ar, json_net,
+                                                       "%pFX", rn_p);
+                       (*output_count)++;
+               } else
+                       (*filtered_count)++;
+
+               bgp_attr_flush(&attr);
+               bgp_dest_unlock_node(dest);
+               return;
+       }
+
+
        subgrp = peer_subgroup(peer, afi, safi);
 
        if (type == bgp_show_adj_route_advertised && subgrp
@@ -14190,6 +14277,8 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
                                              header2, json, json_scode,
                                              json_ocode, wide, detail);
 
+                       const struct prefix *rn_p = bgp_dest_get_prefix(dest);
+
                        for (pi = bgp_dest_get_bgp_path_info(dest); pi;
                             pi = pi->next) {
                                if (pi->peer != peer)
@@ -14198,10 +14287,23 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
                                if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
                                        continue;
 
-                               route_vty_out_tmp(vty, dest,
-                                                 bgp_dest_get_prefix(dest),
-                                                 pi->attr, safi, use_json,
-                                                 json_ar, wide);
+                               if (detail) {
+                                       if (use_json)
+                                               json_net =
+                                                       json_object_new_object();
+                                       bgp_show_path_info(
+                                               NULL /* prefix_rd */, dest, vty,
+                                               bgp, afi, safi, json_net,
+                                               BGP_PATH_SHOW_BESTPATH,
+                                               &display, RPKI_NOT_BEING_USED);
+                                       if (use_json)
+                                               json_object_object_addf(
+                                                       json_ar, json_net,
+                                                       "%pFX", rn_p);
+                               } else
+                                       route_vty_out_tmp(
+                                               vty, dest, rn_p, pi->attr, safi,
+                                               use_json, json_ar, wide);
                                (*output_count)++;
                        }
                }
@@ -14210,7 +14312,8 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
 
 static int peer_adj_routes(struct vty *vty, struct peer *peer, afi_t afi,
                           safi_t safi, enum bgp_show_adj_route_type type,
-                          const char *rmap_name, uint16_t show_flags)
+                          const char *rmap_name, const struct prefix *match,
+                          uint16_t show_flags)
 {
        struct bgp *bgp;
        struct bgp_table *table;
@@ -14336,11 +14439,11 @@ CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
 
                        prefix_rd2str(prd, rd_str, sizeof(rd_str));
 
-                       show_adj_route(vty, peer, table, afi, safi, type,
-                                      rmap_name, json, json_routes, json_scode,
-                                      json_ocode, show_flags, &header1,
-                                      &header2, rd_str, &output_count_per_rd,
-                                      &filtered_count_per_rd);
+                       show_adj_route(
+                               vty, peer, table, afi, safi, type, rmap_name,
+                               json, json_routes, json_scode, json_ocode,
+                               show_flags, &header1, &header2, rd_str, match,
+                               &output_count_per_rd, &filtered_count_per_rd);
 
                        /* Don't include an empty RD in the output! */
                        if (json_routes && (output_count_per_rd > 0))
@@ -14353,7 +14456,7 @@ CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
        } else
                show_adj_route(vty, peer, table, afi, safi, type, rmap_name,
                               json, json_ar, json_scode, json_ocode,
-                              show_flags, &header1, &header2, rd_str,
+                              show_flags, &header1, &header2, rd_str, match,
                               &output_count, &filtered_count);
 
        if (use_json) {
@@ -14378,7 +14481,7 @@ CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
 
                vty_json(vty, json);
        } else if (output_count > 0) {
-               if (filtered_count > 0)
+               if (!match && filtered_count > 0)
                        vty_out(vty,
                                "\nTotal number of prefixes %ld (%ld filtered)\n",
                                output_count, filtered_count);
@@ -14392,7 +14495,7 @@ CPP_NOTICE("Drop `bgpOriginCodes` from JSON outputs")
 
 DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
        show_ip_bgp_instance_neighbor_bestpath_route_cmd,
-       "show [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] neighbors <A.B.C.D|X:X::X:X|WORD> bestpath-routes [json$uj | wide$wide]",
+       "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR " [" BGP_SAFI_WITH_LABEL_CMD_STR "]] neighbors <A.B.C.D|X:X::X:X|WORD> bestpath-routes [detail$detail] [json$uj | wide$wide]",
        SHOW_STR
        IP_STR
        BGP_STR
@@ -14404,6 +14507,7 @@ DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
        "Neighbor to display information about\n"
        "Neighbor on BGP configured interface\n"
        "Display the routes selected by best path\n"
+       "Display detailed version of routes\n"
        JSON_STR
        "Increase table width for longer prefixes\n")
 {
@@ -14417,6 +14521,9 @@ DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
        int idx = 0;
        uint16_t show_flags = 0;
 
+       if (detail)
+               SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
+
        if (uj)
                SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
 
@@ -14436,13 +14543,13 @@ DEFPY (show_ip_bgp_instance_neighbor_bestpath_route,
        if (!peer)
                return CMD_WARNING;
 
-       return peer_adj_routes(vty, peer, afi, safi, type, rmap_name,
+       return peer_adj_routes(vty, peer, afi, safi, type, rmap_name, NULL,
                               show_flags);
 }
 
 DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
       show_ip_bgp_instance_neighbor_advertised_route_cmd,
-      "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR " [" BGP_SAFI_WITH_LABEL_CMD_STR "]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map RMAP_NAME$route_map] [detail$detail] [json$uj | wide$wide]",
+      "show [ip] bgp [<view|vrf> VIEWVRFNAME] [" BGP_AFI_CMD_STR " [" BGP_SAFI_WITH_LABEL_CMD_STR "]] [all$all] neighbors <A.B.C.D|X:X::X:X|WORD> <advertised-routes|received-routes|filtered-routes> [route-map RMAP_NAME$route_map] [<A.B.C.D/M|X:X::X:X/M>$prefix | detail$detail] [json$uj | wide$wide]",
       SHOW_STR
       IP_STR
       BGP_STR
@@ -14459,6 +14566,8 @@ DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
       "Display the filtered routes received from neighbor\n"
       "Route-map to modify the attributes\n"
       "Name of the route map\n"
+      "IPv4 prefix\n"
+      "IPv6 prefix\n"
       "Display detailed version of routes\n"
       JSON_STR
       "Increase table width for longer prefixes\n")
@@ -14475,7 +14584,7 @@ DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
        struct listnode *node;
        struct bgp *abgp;
 
-       if (detail)
+       if (detail || prefix_str)
                SET_FLAG(show_flags, BGP_SHOW_OPT_ROUTES_DETAIL);
 
        if (uj) {
@@ -14517,7 +14626,7 @@ DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
 
        if (!all)
                return peer_adj_routes(vty, peer, afi, safi, type, route_map,
-                                      show_flags);
+                                      prefix_str ? prefix : NULL, show_flags);
        if (uj)
                vty_out(vty, "{\n");
 
@@ -14545,7 +14654,7 @@ DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
                                                                 false));
 
                                peer_adj_routes(vty, peer, afi, safi, type,
-                                               route_map, show_flags);
+                                               route_map, prefix, show_flags);
                        }
                }
        } else {
@@ -14569,7 +14678,7 @@ DEFPY(show_ip_bgp_instance_neighbor_advertised_route,
                                                                 false));
 
                                peer_adj_routes(vty, peer, afi, safi, type,
-                                               route_map, show_flags);
+                                               route_map, prefix, show_flags);
                        }
                }
        }