#include "bgpd/bgp_flowspec_util.h"
#include "bgpd/bgp_flowspec_private.h"
#include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_pbr.h"
/* Local Structures and variables declarations
* This code block hosts the struct declared that host the flowspec rules
{FLOWSPEC_SRC_PORT, "srcp"},
{FLOWSPEC_ICMP_TYPE, "type"},
{FLOWSPEC_ICMP_CODE, "code"},
- {FLOWSPEC_TCP_FLAGS, "flags"},
+ {FLOWSPEC_TCP_FLAGS, "tcp"},
{FLOWSPEC_PKT_LEN, "pktlen"},
{FLOWSPEC_DSCP, "dscp"},
{FLOWSPEC_FRAGMENT, "pktfrag"},
ptr += len_written;
break;
case FLOWSPEC_TCP_FLAGS:
- ret = bgp_flowspec_tcpflags_decode(
+ ret = bgp_flowspec_bitmask_decode(
type_util,
nlri_content+offset,
len - offset,
ptr += len_written;
break;
case FLOWSPEC_FRAGMENT:
- ret = bgp_flowspec_fragment_type_decode(
- type_util,
- nlri_content + offset,
- len - offset, local_string,
- &error);
+ ret = bgp_flowspec_bitmask_decode(
+ type_util,
+ nlri_content+offset,
+ len - offset,
+ local_string, &error);
if (ret <= 0)
break;
if (json_path) {
else
json_nlri_path = json_paths;
}
- if (display == NLRI_STRING_FORMAT_LARGE)
+ if (display == NLRI_STRING_FORMAT_LARGE && binfo)
vty_out(vty, "BGP flowspec entry: (flags 0x%x)\n",
binfo->flags);
bgp_fs_nlri_get_string((unsigned char *)
XFREE(MTYPE_ECOMMUNITY_STR, s);
}
peer_uptime(binfo->uptime, timebuf, BGP_UPTIME_LEN, 0, NULL);
- if (display == NLRI_STRING_FORMAT_LARGE)
- vty_out(vty, "\tup for %8s\n", timebuf);
- else if (json_paths) {
+ if (display == NLRI_STRING_FORMAT_LARGE) {
+ vty_out(vty, "\treceived for %8s\n", timebuf);
+ } else if (json_paths) {
json_time_path = json_object_new_object();
json_object_string_add(json_time_path,
"time", timebuf);
if (display == NLRI_STRING_FORMAT_JSON)
json_object_array_add(json_paths, json_time_path);
}
+ if (display == NLRI_STRING_FORMAT_LARGE) {
+ struct bgp_info_extra *extra = bgp_info_extra_get(binfo);
+ if (extra->bgp_fs_pbr) {
+ struct listnode *node;
+ struct bgp_pbr_match_entry *bpme;
+ struct bgp_pbr_match *bpm;
+ bool list_began = false;
+ struct list *list_bpm;
+
+ list_bpm = list_new();
+ if (listcount(extra->bgp_fs_pbr))
+ vty_out(vty, "\tinstalled in PBR");
+ for (ALL_LIST_ELEMENTS_RO(extra->bgp_fs_pbr,
+ node, bpme)) {
+ bpm = bpme->backpointer;
+ if (listnode_lookup(list_bpm, bpm))
+ continue;
+ listnode_add(list_bpm, bpm);
+ if (!list_began) {
+ vty_out(vty, " (");
+ list_began = true;
+ } else
+ vty_out(vty, ", ");
+ vty_out(vty, "%s", bpm->ipset_name);
+ }
+ if (list_began)
+ vty_out(vty, ")");
+ vty_out(vty, "\n");
+ list_delete_and_null(&list_bpm);
+ } else
+ vty_out(vty, "\tnot installed in PBR\n");
+ }
}
int bgp_show_table_flowspec(struct vty *vty, struct bgp *bgp, afi_t afi,
return CMD_SUCCESS;
}
+int bgp_fs_config_write_pbr(struct vty *vty, struct bgp *bgp,
+ afi_t afi, safi_t safi)
+{
+ struct bgp_pbr_interface *pbr_if;
+ bool declare_node = false;
+ struct bgp_pbr_config *bgp_pbr_cfg = bgp->bgp_pbr_cfg;
+ struct bgp_pbr_interface_head *head;
+ bool bgp_pbr_interface_any;
+
+ if (!bgp_pbr_cfg || safi != SAFI_FLOWSPEC || afi != AFI_IP)
+ return 0;
+ head = &(bgp_pbr_cfg->ifaces_by_name_ipv4);
+ bgp_pbr_interface_any = bgp_pbr_cfg->pbr_interface_any_ipv4;
+ if (!RB_EMPTY(bgp_pbr_interface_head, head) ||
+ !bgp_pbr_interface_any)
+ declare_node = true;
+ RB_FOREACH (pbr_if, bgp_pbr_interface_head, head) {
+ vty_out(vty, " local-install %s\n", pbr_if->name);
+ }
+ return declare_node ? 1 : 0;
+}
+
+static int bgp_fs_local_install_interface(struct bgp *bgp,
+ const char *no, const char *ifname)
+{
+ struct bgp_pbr_interface *pbr_if;
+ struct bgp_pbr_config *bgp_pbr_cfg = bgp->bgp_pbr_cfg;
+ struct bgp_pbr_interface_head *head;
+ bool *bgp_pbr_interface_any;
+
+ if (!bgp_pbr_cfg)
+ return CMD_SUCCESS;
+ head = &(bgp_pbr_cfg->ifaces_by_name_ipv4);
+ bgp_pbr_interface_any = &(bgp_pbr_cfg->pbr_interface_any_ipv4);
+ if (no) {
+ if (!ifname) {
+ if (*bgp_pbr_interface_any) {
+ *bgp_pbr_interface_any = false;
+ /* remove all other interface list */
+ bgp_pbr_reset(bgp, AFI_IP);
+ }
+ return CMD_SUCCESS;
+ }
+ pbr_if = bgp_pbr_interface_lookup(ifname, head);
+ if (!pbr_if)
+ return CMD_SUCCESS;
+ RB_REMOVE(bgp_pbr_interface_head, head, pbr_if);
+ return CMD_SUCCESS;
+ }
+ if (ifname) {
+ pbr_if = bgp_pbr_interface_lookup(ifname, head);
+ if (pbr_if)
+ return CMD_SUCCESS;
+ pbr_if = XCALLOC(MTYPE_TMP,
+ sizeof(struct bgp_pbr_interface));
+ strlcpy(pbr_if->name, ifname, INTERFACE_NAMSIZ);
+ RB_INSERT(bgp_pbr_interface_head, head, pbr_if);
+ *bgp_pbr_interface_any = false;
+ } else {
+ /* set to default */
+ if (!*bgp_pbr_interface_any) {
+ /* remove all other interface list
+ */
+ bgp_pbr_reset(bgp, AFI_IP);
+ *bgp_pbr_interface_any = true;
+ }
+ }
+ return CMD_SUCCESS;
+}
+
+DEFUN (bgp_fs_local_install_ifname,
+ bgp_fs_local_install_ifname_cmd,
+ "[no] local-install INTERFACE",
+ NO_STR
+ "Apply local policy routing\n"
+ "Interface name\n")
+{
+ struct bgp *bgp = VTY_GET_CONTEXT(bgp);
+ int idx = 0;
+ const char *no = strmatch(argv[0]->text, (char *)"no") ? "no" : NULL;
+ char *ifname = argv_find(argv, argc, "INTERFACE", &idx) ?
+ argv[idx]->arg : NULL;
+
+ return bgp_fs_local_install_interface(bgp, no, ifname);
+}
+
+extern int bgp_flowspec_display_match_per_ip(afi_t afi,
+ struct bgp_table *rib,
+ struct prefix *match,
+ int prefix_check,
+ struct vty *vty,
+ uint8_t use_json,
+ json_object *json_paths)
+{
+ struct bgp_node *rn;
+ struct prefix *prefix;
+ int display = 0;
+
+ for (rn = bgp_table_top(rib); rn; rn = bgp_route_next(rn)) {
+ prefix = &rn->p;
+
+ if (prefix->family != AF_FLOWSPEC)
+ continue;
+
+ if (bgp_flowspec_contains_prefix(prefix, match, prefix_check)) {
+ route_vty_out_flowspec(vty, &rn->p,
+ rn->info, use_json ?
+ NLRI_STRING_FORMAT_JSON :
+ NLRI_STRING_FORMAT_LARGE,
+ json_paths);
+ display++;
+ }
+ }
+ return display;
+}
+
void bgp_flowspec_vty_init(void)
{
install_element(ENABLE_NODE, &debug_bgp_flowspec_cmd);
install_element(CONFIG_NODE, &debug_bgp_flowspec_cmd);
install_element(ENABLE_NODE, &no_debug_bgp_flowspec_cmd);
install_element(CONFIG_NODE, &no_debug_bgp_flowspec_cmd);
+ install_element(BGP_FLOWSPECV4_NODE, &bgp_fs_local_install_ifname_cmd);
}