summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_flowspec.h8
-rw-r--r--bgpd/bgp_flowspec_util.c27
-rw-r--r--bgpd/bgp_flowspec_util.h8
-rw-r--r--bgpd/bgp_flowspec_vty.c68
-rw-r--r--bgpd/bgp_pbr.c231
-rw-r--r--bgpd/bgp_route.c20
-rw-r--r--bgpd/bgp_route.h2
-rw-r--r--bgpd/bgp_zebra.c22
-rw-r--r--zebra/zebra_pbr.c41
-rw-r--r--zebra/zebra_pbr.h2
-rw-r--r--zebra/zebra_vty.c14
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;
}