diff options
| -rw-r--r-- | bgpd/bgp_flowspec.h | 8 | ||||
| -rw-r--r-- | bgpd/bgp_flowspec_util.c | 27 | ||||
| -rw-r--r-- | bgpd/bgp_flowspec_util.h | 8 | ||||
| -rw-r--r-- | bgpd/bgp_flowspec_vty.c | 68 | ||||
| -rw-r--r-- | bgpd/bgp_pbr.c | 231 | ||||
| -rw-r--r-- | bgpd/bgp_route.c | 20 | ||||
| -rw-r--r-- | bgpd/bgp_route.h | 2 | ||||
| -rw-r--r-- | bgpd/bgp_zebra.c | 22 | ||||
| -rw-r--r-- | zebra/zebra_pbr.c | 41 | ||||
| -rw-r--r-- | zebra/zebra_pbr.h | 2 | ||||
| -rw-r--r-- | zebra/zebra_vty.c | 14 |
11 files changed, 265 insertions, 178 deletions
diff --git a/bgpd/bgp_flowspec.h b/bgpd/bgp_flowspec.h index 5dd2c3931a..9f69dbedda 100644 --- a/bgpd/bgp_flowspec.h +++ b/bgpd/bgp_flowspec.h @@ -50,4 +50,12 @@ extern void route_vty_out_flowspec(struct vty *vty, struct prefix *p, extern int bgp_fs_config_write_pbr(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi); +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); + #endif /* _FRR_BGP_FLOWSPEC_H */ diff --git a/bgpd/bgp_flowspec_util.c b/bgpd/bgp_flowspec_util.c index 1b87427661..6408337a5f 100644 --- a/bgpd/bgp_flowspec_util.c +++ b/bgpd/bgp_flowspec_util.c @@ -73,9 +73,9 @@ static int bgp_flowspec_call_non_opaque_decode(uint8_t *nlri_content, int len, return ret; } -static bool bgp_flowspec_contains_prefix(struct prefix *pfs, - struct prefix *input, - int prefix_check) +bool bgp_flowspec_contains_prefix(struct prefix *pfs, + struct prefix *input, + int prefix_check) { uint32_t offset = 0; int type; @@ -564,24 +564,3 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len, } return error; } - - -struct bgp_node *bgp_flowspec_get_match_per_ip(afi_t afi, - struct bgp_table *rib, - struct prefix *match, - int prefix_check) -{ - struct bgp_node *rn; - struct prefix *prefix; - - 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)) - return rn; - } - return NULL; -} diff --git a/bgpd/bgp_flowspec_util.h b/bgpd/bgp_flowspec_util.h index 2d16e57a36..9bf05847d3 100644 --- a/bgpd/bgp_flowspec_util.h +++ b/bgpd/bgp_flowspec_util.h @@ -50,8 +50,8 @@ struct bgp_pbr_entry_main; extern int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len, struct bgp_pbr_entry_main *bpem); -extern struct bgp_node *bgp_flowspec_get_match_per_ip(afi_t afi, - struct bgp_table *rib, - struct prefix *match, - int prefix_check); +extern bool bgp_flowspec_contains_prefix(struct prefix *pfs, + struct prefix *input, + int prefix_check); + #endif /* _FRR_BGP_FLOWSPEC_UTIL_H */ diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c index c695e7f125..ace888c78d 100644 --- a/bgpd/bgp_flowspec_vty.c +++ b/bgpd/bgp_flowspec_vty.c @@ -332,16 +332,32 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p, 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; + int unit = 0; + struct list *list_bpm; - bpme = (struct bgp_pbr_match_entry *)extra->bgp_fs_pbr; - bpm = bpme->backpointer; - vty_out(vty, "\tinstalled in PBR"); - if (bpm) - vty_out(vty, " (%s)\n", bpm->ipset_name); - else - vty_out(vty, "\n"); + 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 (unit == 0) + vty_out(vty, " ("); + else + vty_out(vty, ", "); + vty_out(vty, "%s", bpm->ipset_name); + unit++; + } + if (unit) + vty_out(vty, ")"); + vty_out(vty, "\n"); + list_delete_all_node(list_bpm); } else vty_out(vty, "\tnot installed in PBR\n"); } @@ -444,8 +460,6 @@ int bgp_fs_config_write_pbr(struct vty *vty, struct bgp *bgp, RB_FOREACH (pbr_if, bgp_pbr_interface_head, head) { vty_out(vty, " local-install %s\n", pbr_if->name); } - if (!bgp_pbr_interface_any) - vty_out(vty, " no local-install any\n"); return declare_node ? 1 : 0; } @@ -513,17 +527,34 @@ DEFUN (bgp_fs_local_install_ifname, return bgp_fs_local_install_interface(bgp, no, ifname); } -DEFUN (bgp_fs_local_install_any, - bgp_fs_local_install_any_cmd, - "[no] local-install any", - NO_STR - "Apply local policy routing\n" - "Any Interface\n") +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 *bgp = VTY_GET_CONTEXT(bgp); - const char *no = strmatch(argv[0]->text, (char *)"no") ? "no" : NULL; + struct bgp_node *rn; + struct prefix *prefix; + int display = 0; - return bgp_fs_local_install_interface(bgp, no, NULL); + 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) @@ -532,6 +563,5 @@ void bgp_flowspec_vty_init(void) 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_any_cmd); install_element(BGP_FLOWSPECV4_NODE, &bgp_fs_local_install_ifname_cmd); } diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c index b5ddfd4b21..de475d2dcd 100644 --- a/bgpd/bgp_pbr.c +++ b/bgpd/bgp_pbr.c @@ -231,6 +231,8 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, struct nexthop *nh, float *rate); +static void bgp_pbr_dump_entry(struct bgp_pbr_filter *bpf, bool add); + static bool bgp_pbr_extract_enumerate_unary_opposite( uint8_t unary_operator, struct bgp_pbr_val_mask *and_valmask, @@ -833,12 +835,12 @@ uint32_t bgp_pbr_match_hash_key(void *arg) key = jhash_1word(pbm->vrf_id, 0x4312abde); key = jhash_1word(pbm->flags, key); - key = jhash_1word(pbm->pkt_len_min, key); - key = jhash_1word(pbm->pkt_len_max, key); - key = jhash_1word(pbm->tcp_flags, key); - key = jhash_1word(pbm->tcp_mask_flags, key); - key = jhash_1word(pbm->dscp_value, key); - key = jhash_1word(pbm->fragment, key); + key = jhash(&pbm->pkt_len_min, 2, key); + key = jhash(&pbm->pkt_len_max, 2, key); + key = jhash(&pbm->tcp_flags, 2, key); + key = jhash(&pbm->tcp_mask_flags, 2, key); + key = jhash(&pbm->dscp_value, 1, key); + key = jhash(&pbm->fragment, 1, key); return jhash_1word(pbm->type, key); } @@ -1225,7 +1227,8 @@ static void bgp_pbr_flush_entry(struct bgp *bgp, struct bgp_pbr_action *bpa, /* unlink bgp_info to bpme */ bgp_info = (struct bgp_info *)bpme->bgp_info; extra = bgp_info_extra_get(bgp_info); - extra->bgp_fs_pbr = NULL; + if (extra->bgp_fs_pbr) + listnode_delete(extra->bgp_fs_pbr, bpme); bpme->bgp_info = NULL; } } @@ -1282,7 +1285,13 @@ static int bgp_pbr_get_remaining_entry(struct hash_backet *backet, void *arg) bpm_temp = bpme->backpointer; if (bpm_temp->vrf_id != bpm->vrf_id || bpm_temp->type != bpm->type || - bpm_temp->flags != bpm->flags) + bpm_temp->flags != bpm->flags || + bpm_temp->tcp_flags != bpm->tcp_flags || + bpm_temp->tcp_mask_flags != bpm->tcp_mask_flags || + bpm_temp->pkt_len_min != bpm->pkt_len_min || + bpm_temp->pkt_len_max != bpm->pkt_len_max || + bpm_temp->dscp_value != bpm->dscp_value || + bpm_temp->fragment != bpm->fragment) return HASHWALK_CONTINUE; /* look for remaining bpme */ @@ -1311,6 +1320,9 @@ static void bgp_pbr_policyroute_remove_from_zebra_unit(struct bgp *bgp, dst_port = bpf->dst_port; pkt_len = bpf->pkt_len; + if (BGP_DEBUG(zebra, ZEBRA)) + bgp_pbr_dump_entry(bpf, false); + /* as we don't know information from EC * look for bpm that have the bpm * with vrf_id characteristics @@ -1581,6 +1593,101 @@ static void bgp_pbr_policyroute_remove_from_zebra(struct bgp *bgp, list_delete_all_node(bpof->fragment); } +static void bgp_pbr_dump_entry(struct bgp_pbr_filter *bpf, bool add) +{ + struct bgp_pbr_range_port *src_port; + struct bgp_pbr_range_port *dst_port; + struct bgp_pbr_range_port *pkt_len; + char bufsrc[64], bufdst[64]; + char buffer[64]; + int remaining_len = 0; + char protocol_str[16]; + + if (!bpf) + return; + src_port = bpf->src_port; + dst_port = bpf->dst_port; + pkt_len = bpf->pkt_len; + + protocol_str[0] = '\0'; + if (bpf->tcp_flags && bpf->tcp_flags->mask) + bpf->protocol = IPPROTO_TCP; + if (bpf->protocol) + snprintf(protocol_str, sizeof(protocol_str), + "proto %d", bpf->protocol); + buffer[0] = '\0'; + if (bpf->protocol == IPPROTO_ICMP && src_port && dst_port) + remaining_len += snprintf(buffer, sizeof(buffer), + "type %d, code %d", + src_port->min_port, + dst_port->min_port); + else if (bpf->protocol == IPPROTO_UDP || + bpf->protocol == IPPROTO_TCP) { + + if (src_port && src_port->min_port) + remaining_len += snprintf(buffer, + sizeof(buffer), + "from [%u:%u]", + src_port->min_port, + src_port->max_port ? + src_port->max_port : + src_port->min_port); + if (dst_port && dst_port->min_port) + remaining_len += snprintf(buffer + + remaining_len, + sizeof(buffer) + - remaining_len, + "to [%u:%u]", + dst_port->min_port, + dst_port->max_port ? + dst_port->max_port : + dst_port->min_port); + } + if (pkt_len && (pkt_len->min_port || pkt_len->max_port)) { + remaining_len += snprintf(buffer + remaining_len, + sizeof(buffer) + - remaining_len, + " len [%u:%u]", + pkt_len->min_port, + pkt_len->max_port ? + pkt_len->max_port : + pkt_len->min_port); + } else if (bpf->pkt_len_val) { + remaining_len += snprintf(buffer + remaining_len, + sizeof(buffer) + - remaining_len, + " %s len %u", + bpf->pkt_len_val->mask + ? "!" : "", + bpf->pkt_len_val->val); + } + if (bpf->tcp_flags) { + remaining_len += snprintf(buffer + remaining_len, + sizeof(buffer) + - remaining_len, + "tcpflags %x/%x", + bpf->tcp_flags->val, + bpf->tcp_flags->mask); + } + if (bpf->dscp) { + snprintf(buffer + remaining_len, + sizeof(buffer) + - remaining_len, + "%s dscp %d", + bpf->dscp->mask + ? "!" : "", + bpf->dscp->val); + } + zlog_info("BGP: %s FS PBR from %s to %s, %s %s", + add ? "adding" : "removing", + bpf->src == NULL ? "<all>" : + prefix2str(bpf->src, bufsrc, sizeof(bufsrc)), + bpf->dst == NULL ? "<all>" : + prefix2str(bpf->dst, bufdst, sizeof(bufdst)), + protocol_str, buffer); + +} + static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, struct bgp_info *binfo, struct bgp_pbr_filter *bpf, @@ -1597,6 +1704,7 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, struct bgp_pbr_range_port *src_port; struct bgp_pbr_range_port *dst_port; struct bgp_pbr_range_port *pkt_len; + bool bpme_found = false; if (!bpf) return; @@ -1604,87 +1712,9 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, dst_port = bpf->dst_port; pkt_len = bpf->pkt_len; - if (BGP_DEBUG(zebra, ZEBRA)) { - char bufsrc[64], bufdst[64]; - char buffer[64]; - int remaining_len = 0; - char protocol_str[16]; - - protocol_str[0] = '\0'; - if (bpf->tcp_flags && bpf->tcp_flags->mask) - bpf->protocol = IPPROTO_TCP; - if (bpf->protocol) - snprintf(protocol_str, sizeof(protocol_str), - "proto %d", bpf->protocol); - buffer[0] = '\0'; - if (bpf->protocol == IPPROTO_ICMP && src_port && dst_port) - remaining_len += snprintf(buffer, sizeof(buffer), - "type %d, code %d", - src_port->min_port, dst_port->min_port); - else if (bpf->protocol == IPPROTO_UDP || - bpf->protocol == IPPROTO_TCP) { - - if (src_port && src_port->min_port) - remaining_len += snprintf(buffer, - sizeof(buffer), - "from [%u:%u]", - src_port->min_port, - src_port->max_port ? - src_port->max_port : - src_port->min_port); - if (dst_port && dst_port->min_port) - remaining_len += snprintf(buffer + - remaining_len, - sizeof(buffer) - - remaining_len, - "to [%u:%u]", - dst_port->min_port, - dst_port->max_port ? - dst_port->max_port : - dst_port->min_port); - } - if (pkt_len && (pkt_len->min_port || pkt_len->max_port)) { - remaining_len += snprintf(buffer + remaining_len, - sizeof(buffer) - - remaining_len, - " len [%u:%u]", - pkt_len->min_port, - pkt_len->max_port ? - pkt_len->max_port : - pkt_len->min_port); - } else if (bpf->pkt_len_val) { - remaining_len += snprintf(buffer + remaining_len, - sizeof(buffer) - - remaining_len, - " %s len %u", - bpf->pkt_len_val->mask - ? "!" : "", - bpf->pkt_len_val->val); - } - if (bpf->tcp_flags) { - remaining_len += snprintf(buffer + remaining_len, - sizeof(buffer) - - remaining_len, - "tcpflags %x/%x", - bpf->tcp_flags->val, - bpf->tcp_flags->mask); - } - if (bpf->dscp) { - snprintf(buffer + remaining_len, - sizeof(buffer) - - remaining_len, - "%s dscp %d", - bpf->dscp->mask - ? "!" : "", - bpf->dscp->val); - } - zlog_info("BGP: adding FS PBR from %s to %s, %s %s", - bpf->src == NULL ? "<all>" : - prefix2str(bpf->src, bufsrc, sizeof(bufsrc)), - bpf->dst == NULL ? "<all>" : - prefix2str(bpf->dst, bufdst, sizeof(bufdst)), - protocol_str, buffer); - } + if (BGP_DEBUG(zebra, ZEBRA)) + bgp_pbr_dump_entry(bpf, true); + /* look for bpa first */ memset(&temp3, 0, sizeof(temp3)); if (rate) @@ -1817,8 +1847,21 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, bpme->install_in_progress = false; /* link bgp info to bpme */ bpme->bgp_info = (void *)binfo; - } + } else + bpme_found = true; + /* already installed */ + if (bpme_found && bpme) { + struct bgp_info_extra *extra = bgp_info_extra_get(binfo); + + if (extra && extra->bgp_fs_pbr && + listnode_lookup(extra->bgp_fs_pbr, bpme)) { + if (BGP_DEBUG(pbr, PBR_ERROR)) + zlog_err("%s: entry %p/%p already installed in bgp pbr", + __func__, binfo, bpme); + return; + } + } /* BGP FS: append entry to zebra * - policies are not routing entries and as such * route replace semantics don't necessarily follow @@ -2195,7 +2238,6 @@ void bgp_pbr_update_entry(struct bgp *bgp, struct prefix *p, bool nlri_update) { struct bgp_pbr_entry_main api; - struct bgp_info_extra *extra = bgp_info_extra_get(info); if (afi == AFI_IP6) return; /* IPv6 not supported */ @@ -2212,13 +2254,6 @@ void bgp_pbr_update_entry(struct bgp *bgp, struct prefix *p, __func__); return; } - /* already installed */ - if (nlri_update && extra->bgp_fs_pbr) { - if (BGP_DEBUG(pbr, PBR_ERROR)) - zlog_err("%s: entry %p already installed in bgp pbr", - __func__, info); - return; - } if (bgp_pbr_build_and_validate_entry(p, info, &api) < 0) { if (BGP_DEBUG(pbr, PBR_ERROR)) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index f10f7425c6..a94613df57 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -196,6 +196,10 @@ static void bgp_info_extra_free(struct bgp_info_extra **extra) if (e->bgp_orig) bgp_unlock(e->bgp_orig); + + if ((*extra)->bgp_fs_pbr) + list_delete_all_node((*extra)->bgp_fs_pbr); + (*extra)->bgp_fs_pbr = NULL; XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra); *extra = NULL; @@ -8789,17 +8793,11 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp, bgp_unlock_node(rm); } } else if (safi == SAFI_FLOWSPEC) { - rn = bgp_flowspec_get_match_per_ip(afi, rib, - &match, prefix_check); - if (rn != NULL) { - route_vty_out_flowspec(vty, &rn->p, - rn->info, use_json ? - NLRI_STRING_FORMAT_JSON : - NLRI_STRING_FORMAT_LARGE, - json_paths); - display++; - bgp_unlock_node(rn); - } + display = bgp_flowspec_display_match_per_ip(afi, rib, + &match, prefix_check, + vty, + use_json, + json_paths); } else { header = 1; diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 72923901b8..dfef9a8f79 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -147,7 +147,7 @@ struct bgp_info_extra { */ struct prefix nexthop_orig; /* presence of FS pbr entry */ - void *bgp_fs_pbr; + struct list *bgp_fs_pbr; }; struct bgp_info { diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 714f6791c1..9591fe673f 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1998,7 +1998,7 @@ static int ipset_notify_owner(int command, struct zclient *zclient, bgp_pbim = bgp_pbr_match_ipset_lookup(vrf_id, unique); if (!bgp_pbim) { if (BGP_DEBUG(zebra, ZEBRA)) - zlog_debug("%s: Fail to look BGP match ( %u %u)", + zlog_debug("%s: Fail to look BGP match ( %u, ID %u)", __PRETTY_FUNCTION__, note, unique); return 0; } @@ -2048,7 +2048,7 @@ static int ipset_entry_notify_owner(int command, struct zclient *zclient, unique); if (!bgp_pbime) { if (BGP_DEBUG(zebra, ZEBRA)) - zlog_debug("%s: Fail to look BGP match entry (%u %u)", + zlog_debug("%s: Fail to look BGP match entry (%u, ID %u)", __PRETTY_FUNCTION__, note, unique); return 0; } @@ -2074,7 +2074,9 @@ static int ipset_entry_notify_owner(int command, struct zclient *zclient, /* link bgp_info to bpme */ bgp_info = (struct bgp_info *)bgp_pbime->bgp_info; extra = bgp_info_extra_get(bgp_info); - extra->bgp_fs_pbr = (void *)bgp_pbime; + if (extra->bgp_fs_pbr == NULL) + extra->bgp_fs_pbr = list_new(); + listnode_add(extra->bgp_fs_pbr, bgp_pbime); } break; case ZAPI_IPSET_ENTRY_FAIL_REMOVE: @@ -2587,9 +2589,10 @@ void bgp_send_pbr_ipset_match(struct bgp_pbr_match *pbrim, bool install) if (pbrim->install_in_progress) return; if (BGP_DEBUG(zebra, ZEBRA)) - zlog_debug("%s: name %s type %d %d", + zlog_debug("%s: name %s type %d %d, ID %u", __PRETTY_FUNCTION__, - pbrim->ipset_name, pbrim->type, install); + pbrim->ipset_name, pbrim->type, + install, pbrim->unique); s = zclient->obuf; stream_reset(s); @@ -2615,9 +2618,9 @@ void bgp_send_pbr_ipset_entry_match(struct bgp_pbr_match_entry *pbrime, if (pbrime->install_in_progress) return; if (BGP_DEBUG(zebra, ZEBRA)) - zlog_debug("%s: name %s %d %d", __PRETTY_FUNCTION__, + zlog_debug("%s: name %s %d %d, ID %u", __PRETTY_FUNCTION__, pbrime->backpointer->ipset_name, - pbrime->unique, install); + pbrime->unique, install, pbrime->unique); s = zclient->obuf; stream_reset(s); @@ -2682,9 +2685,10 @@ void bgp_send_pbr_iptable(struct bgp_pbr_action *pba, if (pbm->install_iptable_in_progress) return; if (BGP_DEBUG(zebra, ZEBRA)) - zlog_debug("%s: name %s type %d mark %d %d", + zlog_debug("%s: name %s type %d mark %d %d, ID %u", __PRETTY_FUNCTION__, pbm->ipset_name, - pbm->type, pba->fwmark, install); + pbm->type, pba->fwmark, install, + pbm->unique2); s = zclient->obuf; stream_reset(s); diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c index 74ef25b031..e2217a5d2b 100644 --- a/zebra/zebra_pbr.c +++ b/zebra/zebra_pbr.c @@ -832,6 +832,7 @@ struct zebra_pbr_ipset_entry_unique_display { struct zebra_pbr_env_display { struct zebra_ns *zns; struct vty *vty; + char *name; }; static const char *zebra_pbr_prefix2str(union prefixconstptr pu, @@ -1037,6 +1038,7 @@ void zebra_pbr_show_ipset_list(struct vty *vty, char *ipsetname) } uniqueipset.zns = zns; uniqueipset.vty = vty; + uniqueipset.name = NULL; hash_walk(zns->ipset_hash, zebra_pbr_show_ipset_walkcb, &uniqueipset); } @@ -1060,19 +1062,25 @@ static int zebra_pbr_rule_lookup_fwmark_walkcb(struct hash_backet *backet, return HASHWALK_CONTINUE; } -static int zebra_pbr_show_iptable_walkcb(struct hash_backet *backet, void *arg) +static void zebra_pbr_show_iptable_unit(struct zebra_pbr_iptable *iptable, + struct vty *vty, + struct zebra_ns *zns) { - struct zebra_pbr_iptable *iptable = - (struct zebra_pbr_iptable *)backet->data; - struct zebra_pbr_env_display *env = (struct zebra_pbr_env_display *)arg; - struct vty *vty = env->vty; - struct zebra_ns *zns = env->zns; int ret; uint64_t pkts = 0, bytes = 0; vty_out(vty, "IPtable %s action %s (%u)\n", iptable->ipset_name, iptable->action == ZEBRA_IPTABLES_DROP ? "drop" : "redirect", iptable->unique); + if (iptable->type == IPSET_NET_PORT || + iptable->type == IPSET_NET_PORT_NET) { + if (!(iptable->filter_bm & MATCH_ICMP_SET)) { + if (iptable->filter_bm & PBR_FILTER_DST_PORT) + vty_out(vty, "\t lookup dst port\n"); + else if (iptable->filter_bm & PBR_FILTER_SRC_PORT) + vty_out(vty, "\t lookup src port\n"); + } + } if (iptable->pkt_len_min || iptable->pkt_len_max) { if (!iptable->pkt_len_max) vty_out(vty, "\t pkt len %u\n", @@ -1129,17 +1137,34 @@ static int zebra_pbr_show_iptable_walkcb(struct hash_backet *backet, void *arg) prfl.fwmark); } } +} + +static int zebra_pbr_show_iptable_walkcb(struct hash_backet *backet, void *arg) +{ + struct zebra_pbr_iptable *iptable = + (struct zebra_pbr_iptable *)backet->data; + struct zebra_pbr_env_display *env = (struct zebra_pbr_env_display *)arg; + struct vty *vty = env->vty; + struct zebra_ns *zns = env->zns; + char *iptable_name = env->name; + + if (!iptable_name) + zebra_pbr_show_iptable_unit(iptable, vty, zns); + else if (!strncmp(iptable_name, + iptable->ipset_name, + ZEBRA_IPSET_NAME_SIZE)) + zebra_pbr_show_iptable_unit(iptable, vty, zns); return HASHWALK_CONTINUE; } -void zebra_pbr_show_iptable(struct vty *vty) +void zebra_pbr_show_iptable(struct vty *vty, char *iptable_name) { struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); struct zebra_pbr_env_display env; env.vty = vty; env.zns = zns; - + env.name = iptable_name; hash_walk(zns->iptable_hash, zebra_pbr_show_iptable_walkcb, &env); } diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h index fd83502ae1..0db33d1f8c 100644 --- a/zebra/zebra_pbr.h +++ b/zebra/zebra_pbr.h @@ -235,7 +235,7 @@ extern int zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2); extern void zebra_pbr_init(void); extern void zebra_pbr_show_ipset_list(struct vty *vty, char *ipsetname); -extern void zebra_pbr_show_iptable(struct vty *vty); +extern void zebra_pbr_show_iptable(struct vty *vty, char *iptable); extern void zebra_pbr_iptable_update_interfacelist(struct stream *s, struct zebra_pbr_iptable *zpi); size_t zebra_pbr_tcpflags_snprintf(char *buffer, size_t len, diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 8ee47d2f1b..bed3b7f77c 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -3474,12 +3474,20 @@ DEFUN (show_pbr_ipset, /* policy routing contexts */ DEFUN (show_pbr_iptable, show_pbr_iptable_cmd, - "show pbr iptable", + "show pbr iptable [WORD]", SHOW_STR "Policy-Based Routing\n" - "IPtable Context information\n") + "IPtable Context information\n" + "IPtable Name information\n") { - zebra_pbr_show_iptable(vty); + int idx = 0; + int found = 0; + + found = argv_find(argv, argc, "WORD", &idx); + if (!found) + zebra_pbr_show_iptable(vty, NULL); + else + zebra_pbr_show_iptable(vty, argv[idx]->arg); return CMD_SUCCESS; } |
