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_keepalives.c6
-rw-r--r--bgpd/bgp_pbr.c231
-rw-r--r--bgpd/bgp_route.c44
-rw-r--r--bgpd/bgp_route.h2
-rw-r--r--bgpd/bgp_table.h4
-rw-r--r--bgpd/bgp_updgrp_adv.c68
-rw-r--r--bgpd/bgp_zebra.c22
-rw-r--r--doc/user/bgp.rst140
-rw-r--r--doc/user/rpki.rst54
-rw-r--r--doc/user/zebra.rst7
-rw-r--r--lib/if.c4
-rw-r--r--lib/table.h8
-rw-r--r--lib/vrf.h13
-rw-r--r--pimd/pim_msg.c2
-rw-r--r--tests/bgpd/test_bgp_table.c4
-rw-r--r--tests/bgpd/test_capability.c1
-rw-r--r--tests/lib/test_srcdest_table.c3
-rw-r--r--zebra/interface.c6
-rw-r--r--zebra/kernel_netlink.c2
-rw-r--r--zebra/router-id.c4
-rw-r--r--zebra/zebra_pbr.c41
-rw-r--r--zebra/zebra_pbr.h2
-rw-r--r--zebra/zebra_vty.c30
-rw-r--r--zebra/zebra_vxlan.c1
28 files changed, 451 insertions, 359 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_keepalives.c b/bgpd/bgp_keepalives.c
index 1504893c47..3216683a54 100644
--- a/bgpd/bgp_keepalives.c
+++ b/bgpd/bgp_keepalives.c
@@ -180,6 +180,12 @@ void *bgp_keepalives_start(void *arg)
pthread_cond_init(peerhash_cond, &attrs);
pthread_condattr_destroy(&attrs);
+#ifdef GNU_LINUX
+ pthread_setname_np(fpt->thread, "bgpd_ka");
+#elif defined(OPEN_BSD)
+ pthread_set_name_np(fpt->thread, "bgpd_ka");
+#endif
+
/* initialize peer hashtable */
peerhash = hash_create_size(2048, peer_hash_key, peer_hash_cmp, NULL);
pthread_mutex_lock(peerhash_mtx);
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..4bbc535cdc 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -188,14 +188,17 @@ static void bgp_info_extra_free(struct bgp_info_extra **extra)
struct bgp_info *bi = (struct bgp_info *)e->parent;
if (bi->net)
- bgp_unlock_node((struct bgp_node *)bi->net);
- bi->net = NULL;
+ bi->net = bgp_unlock_node((struct bgp_node *)bi->net);
bgp_info_unlock(e->parent);
e->parent = NULL;
}
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 +8792,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;
@@ -10101,6 +10098,7 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
json_object *json_ocode = NULL;
json_object *json_ar = NULL;
struct peer_af *paf;
+ bool route_filtered;
if (use_json) {
json_scode = json_object_new_object();
@@ -10223,17 +10221,27 @@ static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi,
}
bgp_attr_dup(&attr, ain->attr);
+ route_filtered = false;
+
+ /* Filter prefix using distribute list,
+ * filter list or prefix list
+ */
+ if ((bgp_input_filter(peer, &rn->p, &attr, afi,
+ safi)) == FILTER_DENY)
+ route_filtered = true;
+
+ /* Filter prefix using route-map */
ret = bgp_input_modifier(peer, &rn->p, &attr,
- afi, safi, rmap_name);
+ afi, safi, rmap_name);
- if (type == bgp_show_adj_route_filtered
- && ret != RMAP_DENY) {
+ if (type == bgp_show_adj_route_filtered &&
+ !route_filtered && ret != RMAP_DENY) {
bgp_attr_undup(&attr, ain->attr);
continue;
}
- if (type == bgp_show_adj_route_received
- && ret == RMAP_DENY)
+ if (type == bgp_show_adj_route_received &&
+ (route_filtered || ret == RMAP_DENY))
filtered_count++;
route_vty_out_tmp(vty, &rn->p, &attr, safi,
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_table.h b/bgpd/bgp_table.h
index 60c2cbd4a4..f7eac09546 100644
--- a/bgpd/bgp_table.h
+++ b/bgpd/bgp_table.h
@@ -128,9 +128,9 @@ static inline struct bgp_node *bgp_node_parent_nolock(struct bgp_node *node)
/*
* bgp_unlock_node
*/
-static inline void bgp_unlock_node(struct bgp_node *node)
+static inline struct bgp_node *bgp_unlock_node(struct bgp_node *node)
{
- route_unlock_node(bgp_node_to_rnode(node));
+ return (struct bgp_node *)route_unlock_node(bgp_node_to_rnode(node));
}
/*
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c
index d555006571..1f80470f59 100644
--- a/bgpd/bgp_updgrp_adv.c
+++ b/bgpd/bgp_updgrp_adv.c
@@ -662,8 +662,7 @@ void subgroup_announce_route(struct update_subgroup *subgrp)
void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
{
struct bgp *bgp;
- struct attr attr;
- struct aspath *aspath;
+ struct bgp_info *info, init_info;
struct prefix p;
struct peer *from;
struct bgp_node *rn;
@@ -686,48 +685,50 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
bgp = peer->bgp;
from = bgp->peer_self;
- bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
- aspath = attr.aspath;
-
- attr.local_pref = bgp->default_local_pref;
+ init_info.attr = NULL;
+ info = &init_info;
memset(&p, 0, sizeof(p));
p.family = afi2family(afi);
p.prefixlen = 0;
- if ((afi == AFI_IP6) || peer_cap_enhe(peer, afi, safi)) {
- /* IPv6 global nexthop must be included. */
- attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
-
- /* If the peer is on shared nextwork and we have link-local
- nexthop set it. */
- if (peer->shared_network
- && !IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_local))
- attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
- }
-
if (peer->default_rmap[afi][safi].name) {
SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_DEFAULT);
for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
rn = bgp_route_next(rn)) {
for (ri = rn->info; ri; ri = ri->next) {
- struct attr dummy_attr;
- struct bgp_info info;
-
- /* Provide dummy so the route-map can't modify
- * the attributes */
- bgp_attr_dup(&dummy_attr, ri->attr);
- info.peer = ri->peer;
- info.attr = &dummy_attr;
+ struct bgp_info tmp_info;
+
+ tmp_info.peer = ri->peer;
+ tmp_info.attr = ri->attr;
+
+ /* Reset attributes every time to avoid \
+ * unexpected as-path prepends */
+ bgp_attr_default_set(tmp_info.attr,
+ BGP_ORIGIN_IGP);
+
+ if ((afi == AFI_IP6)
+ || peer_cap_enhe(peer, afi, safi)) {
+ /* IPv6 global nexthop must be included.
+ */
+ tmp_info.attr->mp_nexthop_len =
+ BGP_ATTR_NHLEN_IPV6_GLOBAL;
+
+ /* If the peer is on shared nextwork and
+ * we have link-local nexthop set it. */
+ if (peer->shared_network
+ && !IN6_IS_ADDR_UNSPECIFIED(
+ &peer->nexthop.v6_local))
+ tmp_info.attr->mp_nexthop_len =
+ BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL;
+ }
ret = route_map_apply(
peer->default_rmap[afi][safi].map,
- &rn->p, RMAP_BGP, &info);
+ &rn->p, RMAP_BGP, &tmp_info);
+
+ info = &tmp_info;
- /* The route map might have set attributes. If
- * we don't flush them
- * here, they will be leaked. */
- bgp_attr_flush(&dummy_attr);
if (ret != RMAP_DENYMATCH)
break;
}
@@ -749,12 +750,13 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
SUBGRP_STATUS_DEFAULT_ORIGINATE)) {
if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) {
- bgp_attr_add_gshut_community(&attr);
+ bgp_attr_add_gshut_community(info->attr);
}
SET_FLAG(subgrp->sflags,
SUBGRP_STATUS_DEFAULT_ORIGINATE);
- subgroup_default_update_packet(subgrp, &attr, from);
+ subgroup_default_update_packet(subgrp, info->attr,
+ from);
/* The 'neighbor x.x.x.x default-originate' default will
* act as an
@@ -774,8 +776,6 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw)
BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE);
}
}
-
- aspath_unintern(&aspath);
}
/*
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/doc/user/bgp.rst b/doc/user/bgp.rst
index 579b0b6497..734c9cabd0 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -31,9 +31,9 @@ be specified (:ref:`common-invocation-options`).
.. option:: -l, --listenon
- Specify a specific IP address for bgpd to listen on, rather than its
- default of INADDR_ANY / IN6ADDR_ANY. This can be useful to constrain bgpd
- to an internal address, or to run multiple bgpd processes on one host.
+ Specify a specific IP address for bgpd to listen on, rather than its default
+ of ``0.0.0.0`` / ``::``. This can be useful to constrain bgpd to an internal
+ address, or to run multiple bgpd processes on one host.
.. _bgp-basic-concepts:
@@ -45,26 +45,33 @@ Basic Concepts
Autonomous Systems
------------------
-The :abbr:`AS (Autonomous System)` number is one of the essential element of
+From :rfc:`1930`:
+
+ An AS is a connected group of one or more IP prefixes run by one or more
+ network operators which has a SINGLE and CLEARLY DEFINED routing policy.
+
+Each AS has an identifying number associated with it called an :abbr:`ASN
+(Autonomous System Number)`. This is a two octet value ranging in value from 1
+to 65535. The AS numbers 64512 through 65535 are defined as private AS numbers.
+Private AS numbers must not be advertised on the global Internet.
+
+The :abbr:`ASN (Autonomous System Number)` is one of the essential elements of
BGP. BGP is a distance vector routing protocol, and the AS-Path framework
-provides distance vector metric and loop detection to BGP. :rfc:`1930` provides
-some background on the concepts of an AS.
+provides distance vector metric and loop detection to BGP.
-The AS number is a two octet value, ranging in value from 1 to 65535. The AS
-numbers 64512 through 65535 are defined as private AS numbers. Private AS
-numbers must not to be advertised in the global Internet.
+.. seealso:: :rfc:`1930`
.. _bgp-address-families:
Address Families
----------------
-Multiprotocol BGP enables BGP to carry routing information for multiple Network
-Layer protocols. BGP supports an Address Family Identifier (AFI) for IPv4 and
-IPv6. Support is also provided for multiple sets of per-AFI information via the
-BGP Subsequent Address Family Identifier (SAFI). FRR supports SAFIs for unicast
-information, labeled information :rfc:`3107` and :rfc:`8277`, and Layer 3 VPN
-information :rfc:`4364` and :rfc:`4659`.
+Multiprotocol extensions enable BGP to carry routing information for multiple
+network layer protocols. BGP supports an Address Family Identifier (AFI) for
+IPv4 and IPv6. Support is also provided for multiple sets of per-AFI
+information via the BGP Subsequent Address Family Identifier (SAFI). FRR
+supports SAFIs for unicast information, labeled information (:rfc:`3107` and
+:rfc:`8277`), and Layer 3 VPN information (:rfc:`4364` and :rfc:`4659`).
.. _bgp-route-selection:
@@ -718,35 +725,30 @@ Defining Peers
Configuring Peers
^^^^^^^^^^^^^^^^^
-.. index:: neighbor PEER shutdown
-.. clicmd:: neighbor PEER shutdown
-
-.. index:: no neighbor PEER shutdown
-.. clicmd:: no neighbor PEER shutdown
+.. index:: [no] neighbor PEER shutdown
+.. clicmd:: [no] neighbor PEER shutdown
Shutdown the peer. We can delete the neighbor's configuration by
``no neighbor PEER remote-as ASN`` but all configuration of the neighbor
will be deleted. When you want to preserve the configuration, but want to
drop the BGP peer, use this syntax.
-.. index:: neighbor PEER ebgp-multihop
-.. clicmd:: neighbor PEER ebgp-multihop
-
-.. index:: no neighbor PEER ebgp-multihop
-.. clicmd:: no neighbor PEER ebgp-multihop
-
+.. index:: [no] neighbor PEER disable-connected-check
+.. clicmd:: [no] neighbor PEER disable-connected-check
-.. index:: neighbor PEER description ...
-.. clicmd:: neighbor PEER description ...
+ Allow peerings between directly connected eBGP peers using loopback
+ addresses.
+.. index:: [no] neighbor PEER ebgp-multihop
+.. clicmd:: [no] neighbor PEER ebgp-multihop
-.. index:: no neighbor PEER description ...
-.. clicmd:: no neighbor PEER description ...
+.. index:: [no] neighbor PEER description ...
+.. clicmd:: [no] neighbor PEER description ...
Set description of the peer.
-.. index:: neighbor PEER version VERSION
-.. clicmd:: neighbor PEER version VERSION
+.. index:: [no] neighbor PEER version VERSION
+.. clicmd:: [no] neighbor PEER version VERSION
Set up the neighbor's BGP version. `version` can be `4`, `4+` or `4-`. BGP
version `4` is the default value used for BGP peering. BGP version `4+`
@@ -755,12 +757,8 @@ Configuring Peers
revision 00's Multiprotocol Extensions for BGP-4. Some routing software is
still using this version.
-.. index:: neighbor PEER interface IFNAME
-.. clicmd:: neighbor PEER interface IFNAME
-
-
-.. index:: no neighbor PEER interface IFNAME
-.. clicmd:: no neighbor PEER interface IFNAME
+.. index:: [no] neighbor PEER interface IFNAME
+.. clicmd:: [no] neighbor PEER interface IFNAME
When you connect to a BGP peer over an IPv6 link-local address, you have to
specify the IFNAME of the interface used for the connection. To specify
@@ -770,24 +768,16 @@ Configuring Peers
This command is deprecated and may be removed in a future release. Its use
should be avoided.
-.. index:: neighbor PEER next-hop-self [all]
-.. clicmd:: neighbor PEER next-hop-self [all]
-
-
-.. index:: no neighbor PEER next-hop-self [all]
-.. clicmd:: no neighbor PEER next-hop-self [all]
+.. index:: [no] neighbor PEER next-hop-self [all]
+.. clicmd:: [no] neighbor PEER next-hop-self [all]
This command specifies an announced route's nexthop as being equivalent to
the address of the bgp router if it is learned via eBGP. If the optional
keyword `all` is specified the modification is done also for routes learned
via iBGP.
-.. index:: neighbor PEER update-source <IFNAME|ADDRESS>
-.. clicmd:: neighbor PEER update-source <IFNAME|ADDRESS>
-
-
-.. index:: no neighbor PEER update-source
-.. clicmd:: no neighbor PEER update-source
+.. index:: [no] neighbor PEER update-source <IFNAME|ADDRESS>
+.. clicmd:: [no] neighbor PEER update-source <IFNAME|ADDRESS>
Specify the IPv4 source address to use for the :abbr:`BGP` session to this
neighbour, may be specified as either an IPv4 address directly or as an
@@ -801,11 +791,8 @@ Configuring Peers
neighbor bar update-source lo0
-.. index:: neighbor PEER default-originate
-.. clicmd:: neighbor PEER default-originate
-
-.. index:: no neighbor PEER default-originate
-.. clicmd:: no neighbor PEER default-originate
+.. index:: [no] neighbor PEER default-originate
+.. clicmd:: [no] neighbor PEER default-originate
*bgpd*'s default is to not announce the default route (0.0.0.0/0) even if it
is in routing table. When you want to announce default routes to the peer,
@@ -817,37 +804,22 @@ Configuring Peers
.. index:: neighbor PEER send-community
.. clicmd:: neighbor PEER send-community
-.. index:: neighbor PEER weight WEIGHT
-.. clicmd:: neighbor PEER weight WEIGHT
-
-
-.. index:: no neighbor PEER weight WEIGHT
-.. clicmd:: no neighbor PEER weight WEIGHT
+.. index:: [no] neighbor PEER weight WEIGHT
+.. clicmd:: [no] neighbor PEER weight WEIGHT
This command specifies a default `weight` value for the neighbor's routes.
-.. index:: neighbor PEER maximum-prefix NUMBER
-.. clicmd:: neighbor PEER maximum-prefix NUMBER
-
-
-.. index:: no neighbor PEER maximum-prefix NUMBER
-.. clicmd:: no neighbor PEER maximum-prefix NUMBER
-
+.. index:: [no] neighbor PEER maximum-prefix NUMBER
+.. clicmd:: [no] neighbor PEER maximum-prefix NUMBER
-.. index:: neighbor PEER local-as AS-NUMBER
-.. clicmd:: neighbor PEER local-as AS-NUMBER
+.. index:: [no] neighbor PEER local-as AS-NUMBER no-prepend
+.. clicmd:: [no] neighbor PEER local-as AS-NUMBER no-prepend
+.. index:: [no] neighbor PEER local-as AS-NUMBER no-prepend replace-as
+.. clicmd:: [no] neighbor PEER local-as AS-NUMBER no-prepend replace-as
-.. index:: neighbor PEER local-as AS-NUMBER no-prepend
-.. clicmd:: neighbor PEER local-as AS-NUMBER no-prepend
-
-
-.. index:: neighbor PEER local-as AS-NUMBER no-prepend replace-as
-.. clicmd:: neighbor PEER local-as AS-NUMBER no-prepend replace-as
-
-
-.. index:: no neighbor PEER local-as
-.. clicmd:: no neighbor PEER local-as
+.. index:: [no] neighbor PEER local-as AS-NUMBER
+.. clicmd:: [no] neighbor PEER local-as AS-NUMBER
Specify an alternate AS for this BGP process when interacting with the
specified peer. With no modifiers, the specified local-as is prepended to
@@ -865,12 +837,8 @@ Configuring Peers
This command is only allowed for eBGP peers.
-.. index:: neighbor PEER ttl-security hops NUMBER
-.. clicmd:: neighbor PEER ttl-security hops NUMBER
-
-
-.. index:: no neighbor PEER ttl-security hops NUMBER
-.. clicmd:: no neighbor PEER ttl-security hops NUMBER
+.. index:: [no] neighbor PEER ttl-security hops NUMBER
+.. clicmd:: [no] neighbor PEER ttl-security hops NUMBER
This command enforces Generalized TTL Security Mechanism (GTSM), as
specified in RFC 5082. With this command, only neighbors that are the
diff --git a/doc/user/rpki.rst b/doc/user/rpki.rst
index 38b2b68e98..4f271dee74 100644
--- a/doc/user/rpki.rst
+++ b/doc/user/rpki.rst
@@ -60,39 +60,41 @@ Enabling RPKI
This command enables the RPKI configuration mode. Most commands that start
with *rpki* can only be used in this mode.
- When it is used in a telnet session, leaving of this mode cause rpki to be initialized.
+ When it is used in a telnet session, leaving of this mode cause rpki to be
+ initialized.
Executing this command alone does not activate prefix validation. You need
to configure at least one reachable cache server. See section
:ref:`configuring-rpki-rtr-cache-servers` for configuring a cache server.
-.. _configuring-rpki-rtr-cache-servers:
-
.. index:: daemons.conf
- When first installing FRR with RPKI support from the pre-packaged binaries. Remember
- to append '-M rpki' in the /etc/frr/daemons.conf file to the bgpd_options.
-
- bgpd_options=" --daemon -A 127.0.0.1 -M rpki"
- instead of the default setting
- bgpd_options=" --daemon -A 127.0.0.1"
-
-
- Else you will encounter an error when trying to enter RPKI configuration mode. Because
- the rpki module is not loaded when the BGP daemon is initialized.
-
- Examples of the error:
-
- router(config)# debug rpki
- % [BGP] Unknown command: debug rpki
-
- router(config)# rpki
- % [BGP] Unknown command: rpki
-
- Note that the rpki commands will be available in vtysh when running 'find rpki'.
- Even if the RPKI module is NOT loaded.
- The RPKI commands will be unavailable if you try running the same command in the
- cli specific to the BGP daemon.
+ When first installing FRR with RPKI support from the pre-packaged binaries.
+ Remember to append :option:`-M rpki` in the :file:`/etc/frr/daemons.conf`
+ file to ``bgpd_options``, like so::
+
+ bgpd_options=" --daemon -A 127.0.0.1 -M rpki"
+
+ instead of the default setting::
+
+ bgpd_options=" --daemon -A 127.0.0.1"
+
+ Otherwise you will encounter an error when trying to enter RPKI
+ configuration mode due to the ``rpki`` module not being loaded when the BGP
+ daemon is initialized.
+
+ Examples of the error::
+
+ router(config)# debug rpki
+ % [BGP] Unknown command: debug rpki
+
+ router(config)# rpki
+ % [BGP] Unknown command: rpki
+
+ Note that the RPKI commands will be available in vtysh when running ``find
+ rpki`` regardless of whether the module is loaded.
+
+.. _configuring-rpki-rtr-cache-servers:
Configuring RPKI/RTR Cache Servers
----------------------------------
diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst
index 08606c2128..a9431b16e3 100644
--- a/doc/user/zebra.rst
+++ b/doc/user/zebra.rst
@@ -463,7 +463,7 @@ commands in relationship to VRF. Here is an extract of some of those commands:
.. clicmd:: vrf VRF
This command is available on configuration mode. By default, above command
- permits accessing the vrf configuration mode. This mode is available for
+ permits accessing the VRF configuration mode. This mode is available for
both VRFs. It is to be noted that *Zebra* does not create Linux VRF.
The network administrator can however decide to provision this command in
configuration file to provide more clarity about the intended configuration.
@@ -493,7 +493,10 @@ commands in relationship to VRF. Here is an extract of some of those commands:
This command is based on configuration mode. There, for default VRF, this
command is available for all modes. The ``TABLENO`` configured is one of the
- tables from Default *Linux network namespace*.
+ tables from Default *Linux network namespace*. This command is also available
+ on vrf configuration mode, provided that *Zebra* is run with :option:`-n`
+ option. In that case, this command configures a network route in the given
+ ``TABLENO`` of the *Linux network namespace* of the relevant VRF.
.. index:: show ip route vrf VRF
.. clicmd:: show ip route vrf VRF
diff --git a/lib/if.c b/lib/if.c
index 2320093a15..e31ccd8563 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -652,7 +652,7 @@ DEFUN (interface,
/*Pending: need proper vrf name based lookup/(possible creation of VRF)
Imagine forward reference of a vrf by name in this interface config */
if (vrfname)
- VRF_GET_ID(vrf_id, vrfname);
+ VRF_GET_ID(vrf_id, vrfname, false);
#ifdef SUNOS_5
ifp = if_sunwzebra_get(ifname, vrf_id);
@@ -686,7 +686,7 @@ DEFUN_NOSH (no_interface,
vrf_id_t vrf_id = VRF_DEFAULT;
if (argc > 3)
- VRF_GET_ID(vrf_id, vrfname);
+ VRF_GET_ID(vrf_id, vrfname, false);
ifp = if_lookup_by_name(ifname, vrf_id);
diff --git a/lib/table.h b/lib/table.h
index 8304abe59b..ac7df3e695 100644
--- a/lib/table.h
+++ b/lib/table.h
@@ -235,13 +235,17 @@ static inline struct route_node *route_lock_node(struct route_node *node)
}
/* Unlock node. */
-static inline void route_unlock_node(struct route_node *node)
+static inline struct route_node *route_unlock_node(struct route_node *node)
{
assert(node->lock > 0);
(*(unsigned *)&node->lock)--;
- if (node->lock == 0)
+ if (node->lock == 0) {
route_node_delete(node);
+ return NULL;
+ }
+
+ return node;
}
/*
diff --git a/lib/vrf.h b/lib/vrf.h
index 8aa0fc2215..88536eada8 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -111,15 +111,24 @@ extern struct vrf *vrf_get(vrf_id_t, const char *);
extern const char *vrf_id_to_name(vrf_id_t vrf_id);
extern vrf_id_t vrf_name_to_id(const char *);
-#define VRF_GET_ID(V, NAME) \
+#define VRF_GET_ID(V, NAME, USE_JSON) \
do { \
struct vrf *vrf; \
if (!(vrf = vrf_lookup_by_name(NAME))) { \
+ if (USE_JSON) { \
+ vty_out(vty, "{}\n"); \
+ } else { \
+ vty_out(vty, "%% VRF %s not found\n", NAME); \
+ } \
vty_out(vty, "%% VRF %s not found\n", NAME); \
return CMD_WARNING; \
} \
if (vrf->vrf_id == VRF_UNKNOWN) { \
- vty_out(vty, "%% VRF %s not active\n", NAME); \
+ if (USE_JSON) { \
+ vty_out(vty, "{}\n"); \
+ } else { \
+ vty_out(vty, "%% VRF %s not active\n", NAME); \
+ } \
return CMD_WARNING; \
} \
(V) = vrf->vrf_id; \
diff --git a/pimd/pim_msg.c b/pimd/pim_msg.c
index 5d4ddf14e8..63688f87e0 100644
--- a/pimd/pim_msg.c
+++ b/pimd/pim_msg.c
@@ -114,7 +114,7 @@ size_t pim_msg_get_jp_group_size(struct list *sources)
size += sizeof(struct pim_encoded_source_ipv4) * sources->count;
js = listgetdata(listhead(sources));
- if (js && js->up->sg.src.s_addr == INADDR_ANY) {
+ if (js && js->up->sg.src.s_addr == INADDR_ANY && js->is_join) {
struct pim_upstream *child, *up;
struct listnode *up_node;
diff --git a/tests/bgpd/test_bgp_table.c b/tests/bgpd/test_bgp_table.c
index 01ce7480d7..a0382827b9 100644
--- a/tests/bgpd/test_bgp_table.c
+++ b/tests/bgpd/test_bgp_table.c
@@ -116,8 +116,8 @@ static void check_lookup_result(struct list *list, va_list arglist)
assert(prefix_count == listcount(list));
}
-static void do_test(struct bgp_table *table, const char *prefix, uint8_t maxlen,
- ...)
+static void do_test(struct bgp_table *table, const char *prefix,
+ uint32_t maxlen, ...)
{
va_list arglist;
struct list *list = list_new();
diff --git a/tests/bgpd/test_capability.c b/tests/bgpd/test_capability.c
index c75a699a16..4612bdc26b 100644
--- a/tests/bgpd/test_capability.c
+++ b/tests/bgpd/test_capability.c
@@ -821,6 +821,7 @@ static void parse_test(struct peer *peer, struct test_segment *t, int type)
switch (type) {
case CAPABILITY:
len += 2; /* to cover the OPT-Param header */
+ __attribute__ ((fallthrough));
case OPT_PARAM:
printf("len: %u\n", len);
/* peek_for_as4 wants getp at capibility*/
diff --git a/tests/lib/test_srcdest_table.c b/tests/lib/test_srcdest_table.c
index 53180564bd..e717da15b3 100644
--- a/tests/lib/test_srcdest_table.c
+++ b/tests/lib/test_srcdest_table.c
@@ -392,7 +392,8 @@ static void test_state_del_one_route(struct test_state *test, struct prng *prng)
}
assert(rn);
- srcdest_rnode_prefixes(rn, &dst_p, &src_p);
+ srcdest_rnode_prefixes(rn, (const struct prefix **)&dst_p,
+ (const struct prefix **)&src_p);
memcpy(&dst6_p, dst_p, sizeof(dst6_p));
if (src_p)
memcpy(&src6_p, src_p, sizeof(src6_p));
diff --git a/zebra/interface.c b/zebra/interface.c
index 6125ff9a16..1067f9bdc1 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -1417,7 +1417,7 @@ DEFUN (show_interface,
interface_update_stats();
if (argc > 2)
- VRF_GET_ID(vrf_id, argv[3]->arg);
+ VRF_GET_ID(vrf_id, argv[3]->arg, false);
/* All interface print. */
vrf = vrf_lookup_by_id(vrf_id);
@@ -1466,7 +1466,7 @@ DEFUN (show_interface_name_vrf,
interface_update_stats();
- VRF_GET_ID(vrf_id, argv[idx_name]->arg);
+ VRF_GET_ID(vrf_id, argv[idx_name]->arg, false);
/* Specified interface print. */
ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id);
@@ -1560,7 +1560,7 @@ DEFUN (show_interface_desc,
vrf_id_t vrf_id = VRF_DEFAULT;
if (argc > 3)
- VRF_GET_ID(vrf_id, argv[4]->arg);
+ VRF_GET_ID(vrf_id, argv[4]->arg, false);
if_show_description(vty, vrf_id);
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index 8703b01319..cd881dcc24 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -638,7 +638,7 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int),
read_in++;
for (h = (struct nlmsghdr *)buf;
- NLMSG_OK(h, (unsigned int)status);
+ (status >= 0 && NLMSG_OK(h, (unsigned int)status));
h = NLMSG_NEXT(h, status)) {
/* Finish of reading. */
if (h->nlmsg_type == NLMSG_DONE)
diff --git a/zebra/router-id.c b/zebra/router-id.c
index 252b558a8b..3b96b3371d 100644
--- a/zebra/router-id.c
+++ b/zebra/router-id.c
@@ -226,7 +226,7 @@ DEFUN (router_id,
rid.family = AF_INET;
if (argc > 2)
- VRF_GET_ID(vrf_id, argv[idx_name]->arg);
+ VRF_GET_ID(vrf_id, argv[idx_name]->arg, false);
router_id_set(&rid, vrf_id);
@@ -251,7 +251,7 @@ DEFUN (no_router_id,
rid.family = AF_INET;
if (argc > 3)
- VRF_GET_ID(vrf_id, argv[idx_name]->arg);
+ VRF_GET_ID(vrf_id, argv[idx_name]->arg, false);
router_id_set(&rid, vrf_id);
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..4d71682f64 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -1071,7 +1071,7 @@ DEFPY(ip_route_vrf,
return zebra_static_route_leak(
vty, zvrf, nh_zvrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str,
NULL, gate_str, ifname, flag, tag_str, distance_str, label,
- NULL);
+ table_str);
}
/* New RIB. Detailed information for IPv4 route. */
@@ -1808,7 +1808,7 @@ DEFPY (show_route_table_vrf,
vrf_id_t vrf_id = VRF_DEFAULT;
if (vrf_name)
- VRF_GET_ID(vrf_id, vrf_name);
+ VRF_GET_ID(vrf_id, vrf_name, !!json);
zvrf = zebra_vrf_lookup_by_id(vrf_id);
t = zebra_ns_find_table(zvrf->zns, table, afi);
@@ -1831,7 +1831,7 @@ DEFUN (show_ip_nht,
vrf_id_t vrf_id = VRF_DEFAULT;
if (argc == 5)
- VRF_GET_ID(vrf_id, argv[idx_vrf]->arg);
+ VRF_GET_ID(vrf_id, argv[idx_vrf]->arg, false);
zebra_print_rnh_table(vrf_id, AF_INET, vty, RNH_NEXTHOP_TYPE);
return CMD_SUCCESS;
@@ -1871,7 +1871,7 @@ DEFUN (show_ipv6_nht,
vrf_id_t vrf_id = VRF_DEFAULT;
if (argc == 5)
- VRF_GET_ID(vrf_id, argv[idx_vrf]->arg);
+ VRF_GET_ID(vrf_id, argv[idx_vrf]->arg, false);
zebra_print_rnh_table(vrf_id, AF_INET6, vty, RNH_NEXTHOP_TYPE);
return CMD_SUCCESS;
@@ -2037,7 +2037,7 @@ DEFPY (show_route,
vrf_id_t vrf_id = VRF_DEFAULT;
if (vrf_name)
- VRF_GET_ID(vrf_id, vrf_name);
+ VRF_GET_ID(vrf_id, vrf_name, !!json);
vrf = vrf_lookup_by_id(vrf_id);
do_show_ip_route(vty, vrf->name, afi, SAFI_UNICAST, !!fib,
!!json, tag, prefix_str ? prefix : NULL,
@@ -2111,7 +2111,7 @@ DEFPY (show_route_detail,
vrf_id_t vrf_id = VRF_DEFAULT;
if (vrf_name)
- VRF_GET_ID(vrf_id, vrf_name);
+ VRF_GET_ID(vrf_id, vrf_name, false);
table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
if (!table)
@@ -2178,7 +2178,7 @@ DEFPY (show_route_summary,
vrf_id_t vrf_id = VRF_DEFAULT;
if (vrf_name)
- VRF_GET_ID(vrf_id, vrf_name);
+ VRF_GET_ID(vrf_id, vrf_name, false);
table = zebra_vrf_table(afi, SAFI_UNICAST, vrf_id);
if (!table)
@@ -2793,7 +2793,7 @@ DEFUN (show_ipv6_mroute,
vrf_id_t vrf_id = VRF_DEFAULT;
if (argc == 5)
- VRF_GET_ID(vrf_id, argv[4]->arg);
+ VRF_GET_ID(vrf_id, argv[4]->arg, false);
table = zebra_vrf_table(AFI_IP6, SAFI_MULTICAST, vrf_id);
if (!table)
@@ -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;
}
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 06d1b3618c..4955f3f77c 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -244,6 +244,7 @@ static uint32_t num_valid_macs(zebra_vni_t *zvni)
for (hb = hash->index[i]; hb; hb = hb->next) {
mac = (zebra_mac_t *)hb->data;
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
+ || CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
|| !CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO))
num_macs++;
}