back to topotato report
topotato coverage report
Current view: top level - bgpd - bgp_flowspec_vty.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 8 310 2.6 %
Date: 2023-02-24 14:41:08 Functions: 1 10 10.0 %

          Line data    Source code
       1             : /* BGP FlowSpec VTY
       2             :  * Copyright (C) 2018 6WIND
       3             :  *
       4             :  * FRRouting is free software; you can redistribute it and/or modify it
       5             :  * under the terms of the GNU General Public License as published by the
       6             :  * Free Software Foundation; either version 2, or (at your option) any
       7             :  * later version.
       8             :  *
       9             :  * FRRouting is distributed in the hope that it will be useful, but
      10             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             :  * General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License along
      15             :  * with this program; see the file COPYING; if not, write to the Free Software
      16             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      17             :  */
      18             : 
      19             : #include <zebra.h>
      20             : #include "command.h"
      21             : 
      22             : #include "bgpd/bgpd.h"
      23             : #include "bgpd/bgp_table.h"
      24             : #include "bgpd/bgp_attr.h"
      25             : #include "bgpd/bgp_ecommunity.h"
      26             : #include "bgpd/bgp_vty.h"
      27             : #include "bgpd/bgp_route.h"
      28             : #include "bgpd/bgp_aspath.h"
      29             : #include "bgpd/bgp_flowspec.h"
      30             : #include "bgpd/bgp_flowspec_util.h"
      31             : #include "bgpd/bgp_flowspec_private.h"
      32             : #include "bgpd/bgp_debug.h"
      33             : #include "bgpd/bgp_pbr.h"
      34             : 
      35             : /* Local Structures and variables declarations
      36             :  * This code block hosts the struct declared that host the flowspec rules
      37             :  * as well as some structure used to convert to stringx
      38             :  */
      39             : 
      40             : static const struct message bgp_flowspec_display_large[] = {
      41             :         {FLOWSPEC_DEST_PREFIX, "Destination Address"},
      42             :         {FLOWSPEC_SRC_PREFIX, "Source Address"},
      43             :         {FLOWSPEC_IP_PROTOCOL, "IP Protocol"},
      44             :         {FLOWSPEC_PORT, "Port"},
      45             :         {FLOWSPEC_DEST_PORT, "Destination Port"},
      46             :         {FLOWSPEC_SRC_PORT, "Source Port"},
      47             :         {FLOWSPEC_ICMP_TYPE, "ICMP Type"},
      48             :         {FLOWSPEC_ICMP_CODE, "ICMP Code"},
      49             :         {FLOWSPEC_TCP_FLAGS, "TCP Flags"},
      50             :         {FLOWSPEC_PKT_LEN, "Packet Length"},
      51             :         {FLOWSPEC_DSCP, "DSCP field"},
      52             :         {FLOWSPEC_FRAGMENT, "Packet Fragment"},
      53             :         {FLOWSPEC_FLOW_LABEL, "Packet Flow Label"},
      54             :         {0}
      55             : };
      56             : 
      57             : static const struct message bgp_flowspec_display_min[] = {
      58             :         {FLOWSPEC_DEST_PREFIX, "to"},
      59             :         {FLOWSPEC_SRC_PREFIX, "from"},
      60             :         {FLOWSPEC_IP_PROTOCOL, "proto"},
      61             :         {FLOWSPEC_PORT, "port"},
      62             :         {FLOWSPEC_DEST_PORT, "dstp"},
      63             :         {FLOWSPEC_SRC_PORT, "srcp"},
      64             :         {FLOWSPEC_ICMP_TYPE, "type"},
      65             :         {FLOWSPEC_ICMP_CODE, "code"},
      66             :         {FLOWSPEC_TCP_FLAGS, "tcp"},
      67             :         {FLOWSPEC_PKT_LEN, "pktlen"},
      68             :         {FLOWSPEC_DSCP, "dscp"},
      69             :         {FLOWSPEC_FRAGMENT, "pktfrag"},
      70             :         {FLOWSPEC_FLOW_LABEL, "flwlbl"},
      71             :         {0}
      72             : };
      73             : 
      74             : #define FS_STRING_UPDATE(count, ptr, format, remaining_len) do {        \
      75             :                 int _len_written;                                       \
      76             :                                                                         \
      77             :                 if (((format) == NLRI_STRING_FORMAT_DEBUG) && (count)) {\
      78             :                         _len_written = snprintf((ptr), (remaining_len), \
      79             :                                                 ", ");                        \
      80             :                         (remaining_len) -= _len_written;                \
      81             :                         (ptr) += _len_written;                          \
      82             :                 } else if (((format) == NLRI_STRING_FORMAT_MIN)         \
      83             :                            && (count)) {                                \
      84             :                         _len_written = snprintf((ptr), (remaining_len), \
      85             :                                                 " ");                 \
      86             :                         (remaining_len) -= _len_written;                \
      87             :                         (ptr) += _len_written;                          \
      88             :                 }                                                       \
      89             :                 count++;                                                \
      90             :         } while (0)
      91             : 
      92             : /* Parse FLOWSPEC NLRI
      93             :  * passed return_string string has assumed length
      94             :  * BGP_FLOWSPEC_STRING_DISPLAY_MAX
      95             :  */
      96           0 : void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len,
      97             :                             char *return_string, int format,
      98             :                             json_object *json_path,
      99             :                             afi_t afi)
     100             : {
     101           0 :         uint32_t offset = 0;
     102           0 :         int type;
     103           0 :         int ret = 0, error = 0;
     104           0 :         char *ptr = return_string;
     105           0 :         char local_string[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
     106           0 :         int count = 0;
     107           0 :         char extra[2] = "";
     108           0 :         char pre_extra[2] = "";
     109           0 :         const struct message *bgp_flowspec_display;
     110           0 :         enum bgp_flowspec_util_nlri_t type_util;
     111           0 :         int len_string = BGP_FLOWSPEC_STRING_DISPLAY_MAX;
     112           0 :         int len_written;
     113             : 
     114           0 :         if (format == NLRI_STRING_FORMAT_LARGE) {
     115           0 :                 snprintf(pre_extra, sizeof(pre_extra), "\t");
     116           0 :                 snprintf(extra, sizeof(extra), "\n");
     117           0 :                 bgp_flowspec_display = bgp_flowspec_display_large;
     118             :         } else
     119             :                 bgp_flowspec_display = bgp_flowspec_display_min;
     120             :         /* if needed. type_util can be set to other values */
     121           0 :         type_util = BGP_FLOWSPEC_RETURN_STRING;
     122           0 :         error = 0;
     123           0 :         while (offset < len-1 && error >= 0) {
     124           0 :                 type = nlri_content[offset];
     125           0 :                 offset++;
     126           0 :                 switch (type) {
     127           0 :                 case FLOWSPEC_DEST_PREFIX:
     128             :                 case FLOWSPEC_SRC_PREFIX:
     129           0 :                         ret = bgp_flowspec_ip_address(
     130             :                                                 type_util,
     131           0 :                                                 nlri_content+offset,
     132             :                                                 len - offset,
     133             :                                                 local_string, &error,
     134             :                                                 afi, NULL);
     135           0 :                         if (ret <= 0)
     136             :                                 break;
     137           0 :                         if (json_path) {
     138           0 :                                 json_object_string_add(json_path,
     139             :                                      lookup_msg(bgp_flowspec_display, type, ""),
     140             :                                      local_string);
     141           0 :                                 break;
     142             :                         }
     143           0 :                         FS_STRING_UPDATE(count, ptr, format, len_string);
     144           0 :                         len_written = snprintf(ptr, len_string, "%s%s %s%s",
     145             :                                         pre_extra,
     146             :                                         lookup_msg(bgp_flowspec_display,
     147             :                                                    type, ""),
     148             :                                         local_string, extra);
     149           0 :                         len_string -= len_written;
     150           0 :                         ptr += len_written;
     151           0 :                         break;
     152           0 :                 case FLOWSPEC_FLOW_LABEL:
     153             :                 case FLOWSPEC_IP_PROTOCOL:
     154             :                 case FLOWSPEC_PORT:
     155             :                 case FLOWSPEC_DEST_PORT:
     156             :                 case FLOWSPEC_SRC_PORT:
     157             :                 case FLOWSPEC_ICMP_TYPE:
     158             :                 case FLOWSPEC_ICMP_CODE:
     159           0 :                         ret = bgp_flowspec_op_decode(type_util,
     160           0 :                                                      nlri_content+offset,
     161             :                                                      len - offset,
     162             :                                                      local_string, &error);
     163           0 :                         if (ret <= 0)
     164             :                                 break;
     165           0 :                         if (json_path) {
     166           0 :                                 json_object_string_add(json_path,
     167             :                                      lookup_msg(bgp_flowspec_display, type, ""),
     168             :                                      local_string);
     169           0 :                                 break;
     170             :                         }
     171           0 :                         FS_STRING_UPDATE(count, ptr, format, len_string);
     172           0 :                         len_written = snprintf(ptr, len_string, "%s%s %s%s",
     173             :                                         pre_extra,
     174             :                                         lookup_msg(bgp_flowspec_display,
     175             :                                         type, ""),
     176             :                                      local_string, extra);
     177           0 :                         len_string -= len_written;
     178           0 :                         ptr += len_written;
     179           0 :                         break;
     180           0 :                 case FLOWSPEC_TCP_FLAGS:
     181           0 :                         ret = bgp_flowspec_bitmask_decode(
     182             :                                               type_util,
     183           0 :                                               nlri_content+offset,
     184             :                                               len - offset,
     185             :                                               local_string, &error);
     186           0 :                         if (ret <= 0)
     187             :                                 break;
     188           0 :                         if (json_path) {
     189           0 :                                 json_object_string_add(json_path,
     190             :                                      lookup_msg(bgp_flowspec_display,
     191             :                                                 type, ""),
     192             :                                      local_string);
     193           0 :                                 break;
     194             :                         }
     195           0 :                         FS_STRING_UPDATE(count, ptr, format, len_string);
     196           0 :                         len_written = snprintf(ptr, len_string, "%s%s %s%s",
     197             :                                         pre_extra,
     198             :                                         lookup_msg(bgp_flowspec_display,
     199             :                                                    type, ""),
     200             :                                         local_string, extra);
     201           0 :                         len_string -= len_written;
     202           0 :                         ptr += len_written;
     203           0 :                         break;
     204           0 :                 case FLOWSPEC_PKT_LEN:
     205             :                 case FLOWSPEC_DSCP:
     206           0 :                         ret = bgp_flowspec_op_decode(
     207             :                                                 type_util,
     208           0 :                                                 nlri_content + offset,
     209             :                                                 len - offset, local_string,
     210             :                                                 &error);
     211           0 :                         if (ret <= 0)
     212             :                                 break;
     213           0 :                         if (json_path) {
     214           0 :                                 json_object_string_add(json_path,
     215             :                                     lookup_msg(bgp_flowspec_display, type, ""),
     216             :                                     local_string);
     217           0 :                                 break;
     218             :                         }
     219           0 :                         FS_STRING_UPDATE(count, ptr, format, len_string);
     220           0 :                         len_written = snprintf(ptr, len_string, "%s%s %s%s",
     221             :                                         pre_extra,
     222             :                                         lookup_msg(bgp_flowspec_display,
     223             :                                         type, ""),
     224             :                                      local_string, extra);
     225           0 :                         len_string -= len_written;
     226           0 :                         ptr += len_written;
     227           0 :                         break;
     228           0 :                 case FLOWSPEC_FRAGMENT:
     229           0 :                         ret = bgp_flowspec_bitmask_decode(
     230             :                                               type_util,
     231           0 :                                               nlri_content+offset,
     232             :                                               len - offset,
     233             :                                               local_string, &error);
     234           0 :                         if (ret <= 0)
     235             :                                 break;
     236           0 :                         if (json_path) {
     237           0 :                                 json_object_string_add(json_path,
     238             :                                     lookup_msg(bgp_flowspec_display,
     239             :                                                type, ""),
     240             :                                     local_string);
     241           0 :                                 break;
     242             :                         }
     243           0 :                         FS_STRING_UPDATE(count, ptr, format, len_string);
     244           0 :                         len_written = snprintf(ptr, len_string, "%s%s %s%s",
     245             :                                         pre_extra,
     246             :                                         lookup_msg(bgp_flowspec_display,
     247             :                                         type, ""),
     248             :                                         local_string, extra);
     249           0 :                         len_string -= len_written;
     250           0 :                         ptr += len_written;
     251           0 :                         break;
     252           0 :                 default:
     253           0 :                         error = -1;
     254           0 :                         break;
     255             :                 }
     256           0 :                 offset += ret;
     257             :         }
     258           0 : }
     259             : 
     260           0 : void route_vty_out_flowspec(struct vty *vty, const struct prefix *p,
     261             :                             struct bgp_path_info *path, int display,
     262             :                             json_object *json_paths)
     263             : {
     264           0 :         struct attr *attr;
     265           0 :         char return_string[BGP_FLOWSPEC_STRING_DISPLAY_MAX];
     266           0 :         char *s1 = NULL, *s2 = NULL;
     267           0 :         json_object *json_nlri_path = NULL;
     268           0 :         json_object *json_ecom_path = NULL;
     269           0 :         json_object *json_time_path = NULL;
     270           0 :         char timebuf[BGP_UPTIME_LEN];
     271           0 :         struct ecommunity *ipv6_ecomm = NULL;
     272             : 
     273           0 :         if (p == NULL || p->family != AF_FLOWSPEC)
     274           0 :                 return;
     275           0 :         if (json_paths) {
     276           0 :                 if (display == NLRI_STRING_FORMAT_JSON)
     277           0 :                         json_nlri_path = json_object_new_object();
     278             :                 else
     279             :                         json_nlri_path = json_paths;
     280             :         }
     281           0 :         if (display == NLRI_STRING_FORMAT_LARGE && path)
     282           0 :                 vty_out(vty, "BGP flowspec entry: (flags 0x%x)\n",
     283             :                         path->flags);
     284           0 :         bgp_fs_nlri_get_string((unsigned char *)
     285           0 :                                p->u.prefix_flowspec.ptr,
     286           0 :                                p->u.prefix_flowspec.prefixlen,
     287             :                                return_string,
     288             :                                display,
     289             :                                json_nlri_path,
     290             :                                family2afi(p->u.prefix_flowspec
     291           0 :                                           .family));
     292           0 :         if (display == NLRI_STRING_FORMAT_LARGE)
     293           0 :                 vty_out(vty, "%s", return_string);
     294           0 :         else if (display == NLRI_STRING_FORMAT_DEBUG)
     295           0 :                 vty_out(vty, "%s", return_string);
     296           0 :         else if (display == NLRI_STRING_FORMAT_MIN)
     297           0 :                 vty_out(vty, " %-30s", return_string);
     298           0 :         else if (json_paths && display == NLRI_STRING_FORMAT_JSON)
     299           0 :                 json_object_array_add(json_paths, json_nlri_path);
     300           0 :         if (!path)
     301             :                 return;
     302             : 
     303           0 :         if (path->attr)
     304           0 :                 ipv6_ecomm = bgp_attr_get_ipv6_ecommunity(path->attr);
     305             : 
     306           0 :         if (path->attr && (bgp_attr_get_ecommunity(path->attr) || ipv6_ecomm)) {
     307             :                 /* Print attribute */
     308           0 :                 attr = path->attr;
     309           0 :                 if (bgp_attr_get_ecommunity(attr))
     310           0 :                         s1 = ecommunity_ecom2str(bgp_attr_get_ecommunity(attr),
     311             :                                                  ECOMMUNITY_FORMAT_ROUTE_MAP,
     312             :                                                  0);
     313           0 :                 if (ipv6_ecomm)
     314           0 :                         s2 = ecommunity_ecom2str(
     315             :                                 ipv6_ecomm, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
     316           0 :                 if (!s1 && !s2)
     317             :                         return;
     318           0 :                 if (display == NLRI_STRING_FORMAT_LARGE)
     319           0 :                         vty_out(vty, "\t%s%s%s\n", s1 ? s1 : "",
     320           0 :                                 s2 && s1 ? " " : "", s2 ? s2 : "");
     321           0 :                 else if (display == NLRI_STRING_FORMAT_MIN)
     322           0 :                         vty_out(vty, "%s%s", s1 ? s1 : "", s2 ? s2 : "");
     323           0 :                 else if (json_paths) {
     324           0 :                         json_ecom_path = json_object_new_object();
     325           0 :                         if (s1)
     326           0 :                                 json_object_string_add(json_ecom_path,
     327             :                                                        "ecomlist", s1);
     328           0 :                         if (s2)
     329           0 :                                 json_object_string_add(json_ecom_path,
     330             :                                                        "ecom6list", s2);
     331           0 :                         if (display == NLRI_STRING_FORMAT_JSON)
     332           0 :                                 json_object_array_add(json_paths,
     333             :                                                       json_ecom_path);
     334             :                 }
     335           0 :                 if (display == NLRI_STRING_FORMAT_LARGE) {
     336           0 :                         char local_buff[INET6_ADDRSTRLEN];
     337             : 
     338           0 :                         local_buff[0] = '\0';
     339           0 :                         if (p->u.prefix_flowspec.family == AF_INET
     340           0 :                             && attr->nexthop.s_addr != INADDR_ANY)
     341           0 :                                 inet_ntop(AF_INET, &attr->nexthop.s_addr,
     342             :                                           local_buff, sizeof(local_buff));
     343           0 :                         else if (p->u.prefix_flowspec.family == AF_INET6 &&
     344           0 :                                  attr->mp_nexthop_len != 0 &&
     345           0 :                                  attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV4 &&
     346             :                                  attr->mp_nexthop_len != BGP_ATTR_NHLEN_VPNV4)
     347           0 :                                 inet_ntop(AF_INET6, &attr->mp_nexthop_global,
     348             :                                           local_buff, sizeof(local_buff));
     349           0 :                         if (local_buff[0] != '\0')
     350           0 :                                 vty_out(vty, "\tNLRI NH %s\n",
     351             :                                         local_buff);
     352             :                 }
     353           0 :                 XFREE(MTYPE_ECOMMUNITY_STR, s1);
     354           0 :                 XFREE(MTYPE_ECOMMUNITY_STR, s2);
     355             :         }
     356           0 :         peer_uptime(path->uptime, timebuf, BGP_UPTIME_LEN, 0, NULL);
     357           0 :         if (display == NLRI_STRING_FORMAT_LARGE) {
     358           0 :                 vty_out(vty, "\treceived for %8s\n", timebuf);
     359           0 :         } else if (json_paths) {
     360           0 :                 json_time_path = json_object_new_object();
     361           0 :                 json_object_string_add(json_time_path,
     362             :                                        "time", timebuf);
     363           0 :                 if (display == NLRI_STRING_FORMAT_JSON)
     364           0 :                         json_object_array_add(json_paths, json_time_path);
     365             :         }
     366           0 :         if (display == NLRI_STRING_FORMAT_LARGE) {
     367           0 :                 struct bgp_path_info_extra *extra =
     368           0 :                         bgp_path_info_extra_get(path);
     369           0 :                 bool list_began = false;
     370             : 
     371           0 :                 if (extra->bgp_fs_pbr && listcount(extra->bgp_fs_pbr)) {
     372           0 :                         struct listnode *node;
     373           0 :                         struct bgp_pbr_match_entry *bpme;
     374           0 :                         struct bgp_pbr_match *bpm;
     375           0 :                         struct list *list_bpm;
     376             : 
     377           0 :                         list_bpm = list_new();
     378           0 :                         vty_out(vty, "\tinstalled in PBR");
     379           0 :                         for (ALL_LIST_ELEMENTS_RO(extra->bgp_fs_pbr,
     380             :                                                   node, bpme)) {
     381           0 :                                 bpm = bpme->backpointer;
     382           0 :                                 if (listnode_lookup(list_bpm, bpm))
     383           0 :                                         continue;
     384           0 :                                 listnode_add(list_bpm, bpm);
     385           0 :                                 if (!list_began) {
     386           0 :                                         vty_out(vty, " (");
     387           0 :                                         list_began = true;
     388             :                                 } else
     389           0 :                                         vty_out(vty, ", ");
     390           0 :                                 vty_out(vty, "%s", bpm->ipset_name);
     391             :                         }
     392           0 :                         list_delete(&list_bpm);
     393             :                 }
     394           0 :                 if (extra->bgp_fs_iprule && listcount(extra->bgp_fs_iprule)) {
     395           0 :                         struct listnode *node;
     396           0 :                         struct bgp_pbr_rule *bpr;
     397             : 
     398           0 :                         if (!list_began)
     399           0 :                                 vty_out(vty, "\tinstalled in PBR");
     400           0 :                         for (ALL_LIST_ELEMENTS_RO(extra->bgp_fs_iprule,
     401             :                                                   node, bpr)) {
     402           0 :                                 if (!bpr->action)
     403           0 :                                         continue;
     404           0 :                                 if (!list_began) {
     405           0 :                                         vty_out(vty, " (");
     406           0 :                                         list_began = true;
     407             :                                 } else
     408           0 :                                         vty_out(vty, ", ");
     409           0 :                                 vty_out(vty, "-ipv4-rule %d action lookup %u-",
     410             :                                         bpr->priority,
     411           0 :                                         bpr->action->table_id);
     412             :                         }
     413             :                 }
     414           0 :                 if (list_began)
     415           0 :                         vty_out(vty, ")\n");
     416             :                 else
     417           0 :                         vty_out(vty, "\tnot installed in PBR\n");
     418             :         }
     419             : }
     420             : 
     421           0 : int bgp_show_table_flowspec(struct vty *vty, struct bgp *bgp, afi_t afi,
     422             :                             struct bgp_table *table, enum bgp_show_type type,
     423             :                             void *output_arg, bool use_json, int is_last,
     424             :                             unsigned long *output_cum, unsigned long *total_cum)
     425             : {
     426           0 :         struct bgp_path_info *pi;
     427           0 :         struct bgp_dest *dest;
     428           0 :         unsigned long total_count = 0;
     429           0 :         json_object *json_paths = NULL;
     430           0 :         int display = NLRI_STRING_FORMAT_LARGE;
     431             : 
     432           0 :         if (type != bgp_show_type_detail)
     433             :                 return CMD_SUCCESS;
     434             : 
     435           0 :         for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
     436           0 :                 pi = bgp_dest_get_bgp_path_info(dest);
     437           0 :                 if (pi == NULL)
     438           0 :                         continue;
     439           0 :                 if (use_json) {
     440           0 :                         json_paths = json_object_new_array();
     441           0 :                         display = NLRI_STRING_FORMAT_JSON;
     442             :                 }
     443           0 :                 for (; pi; pi = pi->next) {
     444           0 :                         total_count++;
     445           0 :                         route_vty_out_flowspec(vty, bgp_dest_get_prefix(dest),
     446             :                                                pi, display, json_paths);
     447             :                 }
     448           0 :                 if (use_json) {
     449           0 :                         vty_json(vty, json_paths);
     450           0 :                         json_paths = NULL;
     451             :                 }
     452             :         }
     453           0 :         if (total_count && !use_json)
     454           0 :                 vty_out(vty,
     455             :                         "\nDisplayed  %ld flowspec entries\n",
     456             :                         total_count);
     457             :         return CMD_SUCCESS;
     458             : }
     459             : 
     460           0 : DEFUN (debug_bgp_flowspec,
     461             :        debug_bgp_flowspec_cmd,
     462             :        "debug bgp flowspec",
     463             :        DEBUG_STR
     464             :        BGP_STR
     465             :        "BGP allow flowspec debugging entries\n")
     466             : {
     467           0 :         if (vty->node == CONFIG_NODE)
     468           0 :                 DEBUG_ON(flowspec, FLOWSPEC);
     469             :         else {
     470           0 :                 TERM_DEBUG_ON(flowspec, FLOWSPEC);
     471           0 :                 vty_out(vty, "BGP flowspec debugging is on\n");
     472             :         }
     473           0 :         return CMD_SUCCESS;
     474             : }
     475             : 
     476           0 : DEFUN (no_debug_bgp_flowspec,
     477             :        no_debug_bgp_flowspec_cmd,
     478             :        "no debug bgp flowspec",
     479             :        NO_STR
     480             :        DEBUG_STR
     481             :        BGP_STR
     482             :        "BGP allow flowspec debugging entries\n")
     483             : {
     484           0 :         if (vty->node == CONFIG_NODE)
     485           0 :                 DEBUG_OFF(flowspec, FLOWSPEC);
     486             :         else {
     487           0 :                 TERM_DEBUG_OFF(flowspec, FLOWSPEC);
     488           0 :                 vty_out(vty, "BGP flowspec debugging is off\n");
     489             :         }
     490           0 :         return CMD_SUCCESS;
     491             : }
     492             : 
     493           0 : int bgp_fs_config_write_pbr(struct vty *vty, struct bgp *bgp,
     494             :                             afi_t afi, safi_t safi)
     495             : {
     496           0 :         struct bgp_pbr_interface *pbr_if;
     497           0 :         bool declare_node = false;
     498           0 :         struct bgp_pbr_config *bgp_pbr_cfg = bgp->bgp_pbr_cfg;
     499           0 :         struct bgp_pbr_interface_head *head;
     500           0 :         bool bgp_pbr_interface_any;
     501             : 
     502           0 :         if (!bgp_pbr_cfg || safi != SAFI_FLOWSPEC)
     503             :                 return 0;
     504           0 :         if (afi == AFI_IP) {
     505           0 :                 head = &(bgp_pbr_cfg->ifaces_by_name_ipv4);
     506           0 :                 bgp_pbr_interface_any = bgp_pbr_cfg->pbr_interface_any_ipv4;
     507           0 :         } else if (afi == AFI_IP6) {
     508           0 :                 head = &(bgp_pbr_cfg->ifaces_by_name_ipv6);
     509           0 :                 bgp_pbr_interface_any = bgp_pbr_cfg->pbr_interface_any_ipv6;
     510             :         } else {
     511             :                 return 0;
     512             :         }
     513           0 :         if (!RB_EMPTY(bgp_pbr_interface_head, head) ||
     514             :              !bgp_pbr_interface_any)
     515           0 :                 declare_node = true;
     516           0 :         RB_FOREACH (pbr_if, bgp_pbr_interface_head, head) {
     517           0 :                 vty_out(vty, "  local-install %s\n", pbr_if->name);
     518             :         }
     519           0 :         return declare_node ? 1 : 0;
     520             : }
     521             : 
     522           0 : static int bgp_fs_local_install_interface(struct bgp *bgp,
     523             :                                           const char *no, const char *ifname,
     524             :                                           afi_t afi)
     525             : {
     526           0 :         struct bgp_pbr_interface *pbr_if;
     527           0 :         struct bgp_pbr_config *bgp_pbr_cfg = bgp->bgp_pbr_cfg;
     528           0 :         struct bgp_pbr_interface_head *head;
     529           0 :         bool *bgp_pbr_interface_any;
     530             : 
     531           0 :         if (!bgp_pbr_cfg)
     532             :                 return CMD_SUCCESS;
     533           0 :         if (afi == AFI_IP) {
     534           0 :                 head = &(bgp_pbr_cfg->ifaces_by_name_ipv4);
     535           0 :                 bgp_pbr_interface_any = &(bgp_pbr_cfg->pbr_interface_any_ipv4);
     536             :         } else {
     537           0 :                 head = &(bgp_pbr_cfg->ifaces_by_name_ipv6);
     538           0 :                 bgp_pbr_interface_any = &(bgp_pbr_cfg->pbr_interface_any_ipv6);
     539             :         }
     540           0 :         if (no) {
     541           0 :                 if (!ifname) {
     542           0 :                         if (*bgp_pbr_interface_any) {
     543           0 :                                 *bgp_pbr_interface_any = false;
     544             :                                 /* remove all other interface list */
     545           0 :                                 bgp_pbr_reset(bgp, afi);
     546             :                         }
     547           0 :                         return CMD_SUCCESS;
     548             :                 }
     549           0 :                 pbr_if = bgp_pbr_interface_lookup(ifname, head);
     550           0 :                 if (!pbr_if)
     551             :                         return CMD_SUCCESS;
     552           0 :                 RB_REMOVE(bgp_pbr_interface_head, head, pbr_if);
     553           0 :                 return CMD_SUCCESS;
     554             :         }
     555           0 :         if (ifname) {
     556           0 :                 pbr_if = bgp_pbr_interface_lookup(ifname, head);
     557           0 :                 if (pbr_if)
     558             :                         return CMD_SUCCESS;
     559           0 :                 pbr_if = XCALLOC(MTYPE_TMP,
     560             :                                  sizeof(struct bgp_pbr_interface));
     561           0 :                 strlcpy(pbr_if->name, ifname, INTERFACE_NAMSIZ);
     562           0 :                 RB_INSERT(bgp_pbr_interface_head, head, pbr_if);
     563           0 :                 *bgp_pbr_interface_any = false;
     564             :         } else {
     565             :                 /* set to default */
     566           0 :                 if (!*bgp_pbr_interface_any) {
     567             :                         /* remove all other interface list
     568             :                          */
     569           0 :                         bgp_pbr_reset(bgp, afi);
     570           0 :                         *bgp_pbr_interface_any = true;
     571             :                 }
     572             :         }
     573             :         return CMD_SUCCESS;
     574             : }
     575             : 
     576           0 : DEFUN (bgp_fs_local_install_ifname,
     577             :         bgp_fs_local_install_ifname_cmd,
     578             :         "[no] local-install INTERFACE",
     579             :         NO_STR
     580             :         "Apply local policy routing\n"
     581             :         "Interface name\n")
     582             : {
     583           0 :         struct bgp *bgp = VTY_GET_CONTEXT(bgp);
     584           0 :         int idx = 0;
     585           0 :         const char *no = strmatch(argv[0]->text, "no") ? "no" : NULL;
     586           0 :         char *ifname = argv_find(argv, argc, "INTERFACE", &idx) ?
     587           0 :                 argv[idx]->arg : NULL;
     588             : 
     589           0 :         return bgp_fs_local_install_interface(bgp, no, ifname,
     590             :                                               bgp_node_afi(vty));
     591             : }
     592             : 
     593           0 : extern int bgp_flowspec_display_match_per_ip(afi_t afi, struct bgp_table *rib,
     594             :                                              struct prefix *match,
     595             :                                              int prefix_check, struct vty *vty,
     596             :                                              bool use_json,
     597             :                                              json_object *json_paths)
     598             : {
     599           0 :         struct bgp_dest *dest;
     600           0 :         const struct prefix *prefix;
     601           0 :         int display = 0;
     602             : 
     603           0 :         for (dest = bgp_table_top(rib); dest; dest = bgp_route_next(dest)) {
     604           0 :                 prefix = bgp_dest_get_prefix(dest);
     605             : 
     606           0 :                 if (prefix->family != AF_FLOWSPEC)
     607           0 :                         continue;
     608             : 
     609           0 :                 if (bgp_flowspec_contains_prefix(prefix, match, prefix_check)) {
     610           0 :                         route_vty_out_flowspec(
     611             :                                 vty, prefix, bgp_dest_get_bgp_path_info(dest),
     612             :                                 use_json ? NLRI_STRING_FORMAT_JSON
     613             :                                          : NLRI_STRING_FORMAT_LARGE,
     614             :                                 json_paths);
     615           0 :                         display++;
     616             :                 }
     617             :         }
     618           0 :         return display;
     619             : }
     620             : 
     621          34 : void bgp_flowspec_vty_init(void)
     622             : {
     623          34 :         install_element(ENABLE_NODE, &debug_bgp_flowspec_cmd);
     624          34 :         install_element(CONFIG_NODE, &debug_bgp_flowspec_cmd);
     625          34 :         install_element(ENABLE_NODE, &no_debug_bgp_flowspec_cmd);
     626          34 :         install_element(CONFIG_NODE, &no_debug_bgp_flowspec_cmd);
     627          34 :         install_element(BGP_FLOWSPECV4_NODE, &bgp_fs_local_install_ifname_cmd);
     628          34 :         install_element(BGP_FLOWSPECV6_NODE, &bgp_fs_local_install_ifname_cmd);
     629          34 : }

Generated by: LCOV version v1.16-topotato