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 : }
|