summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_bfd.c19
-rw-r--r--bgpd/bgp_bfd.h2
-rw-r--r--bgpd/bgp_fsm.c3
-rw-r--r--bgpd/bgp_nexthop.c13
-rw-r--r--bgpd/bgp_nexthop.h6
-rw-r--r--bgpd/bgp_route.c11
-rw-r--r--bgpd/bgp_routemap.c75
-rw-r--r--doc/user/routemap.rst11
m---------libyang0
-rw-r--r--pimd/pim_cmd.c4
-rw-r--r--pimd/pim_rp.c8
11 files changed, 140 insertions, 12 deletions
diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c
index 1f650aaeb7..5f4db3dfa8 100644
--- a/bgpd/bgp_bfd.c
+++ b/bgpd/bgp_bfd.c
@@ -200,6 +200,25 @@ static void bgp_bfd_update_peer(struct peer *peer)
bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_UPDATE);
}
+/**
+ * bgp_bfd_reset_peer - reinitialise bfd
+ * ensures that bfd state machine is restarted
+ * to be synced with remote bfd
+ */
+void bgp_bfd_reset_peer(struct peer *peer)
+{
+ struct bfd_info *bfd_info;
+
+ if (!peer->bfd_info)
+ return;
+ bfd_info = (struct bfd_info *)peer->bfd_info;
+
+ /* if status is not down, reset bfd */
+ if (bfd_info->status != BFD_STATUS_DOWN)
+ bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER);
+ bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER);
+}
+
/*
* bgp_bfd_update_type - update session type with BFD through zebra.
*/
diff --git a/bgpd/bgp_bfd.h b/bgpd/bgp_bfd.h
index caa5651e3a..b96ebb6c96 100644
--- a/bgpd/bgp_bfd.h
+++ b/bgpd/bgp_bfd.h
@@ -31,6 +31,8 @@ extern void bgp_bfd_register_peer(struct peer *peer);
extern void bgp_bfd_deregister_peer(struct peer *peer);
+extern void bgp_bfd_reset_peer(struct peer *peer);
+
extern void bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer,
char *addr);
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 0051b8d606..f4fbfe4c60 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -1956,8 +1956,7 @@ static int bgp_establish(struct peer *peer)
hash_release(peer->bgp->peerhash, peer);
hash_get(peer->bgp->peerhash, peer, hash_alloc_intern);
- bgp_bfd_deregister_peer(peer);
- bgp_bfd_register_peer(peer);
+ bgp_bfd_reset_peer(peer);
return ret;
}
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index ab0c3a3f11..8e43801d2d 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -612,7 +612,8 @@ int bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer)
}
int bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop,
- struct update_subgroup *subgrp)
+ struct update_subgroup *subgrp,
+ struct peer *exclude)
{
struct bgp_node *rn1 = NULL, *rn2 = NULL;
struct peer_af *paf = NULL;
@@ -632,6 +633,9 @@ int bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop,
return 0;
SUBGRP_FOREACH_PEER (subgrp, paf) {
+ /* Skip peer we're told to exclude - e.g., source of route. */
+ if (paf->peer == exclude)
+ continue;
p.u.prefix6 = paf->peer->su.sin6.sin6_addr;
rn2 = bgp_node_match(bgp->connected_table[AFI_IP6], &p);
@@ -650,7 +654,8 @@ int bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop,
}
int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
- struct update_subgroup *subgrp)
+ struct update_subgroup *subgrp,
+ struct peer *exclude)
{
struct bgp_node *rn1, *rn2;
struct peer_af *paf;
@@ -670,6 +675,10 @@ int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
return 0;
SUBGRP_FOREACH_PEER (subgrp, paf) {
+ /* Skip peer we're told to exclude - e.g., source of route. */
+ if (paf->peer == exclude)
+ continue;
+
p.u.prefix4 = paf->peer->su.sin.sin_addr;
rn2 = bgp_node_match(bgp->connected_table[AFI_IP], &p);
diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h
index af4c0bc047..4a25c83cd5 100644
--- a/bgpd/bgp_nexthop.h
+++ b/bgpd/bgp_nexthop.h
@@ -82,9 +82,11 @@ struct bgp_addrv6 {
extern void bgp_connected_add(struct bgp *bgp, struct connected *c);
extern void bgp_connected_delete(struct bgp *bgp, struct connected *c);
extern int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop,
- struct update_subgroup *subgrp);
+ struct update_subgroup *subgrp,
+ struct peer *exclude);
extern int bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop,
- struct update_subgroup *subgrp);
+ struct update_subgroup *subgrp,
+ struct peer *exclude);
extern int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer);
extern int bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer);
extern int bgp_config_write_scan_time(struct vty *);
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index ad089d9d25..0fdf2d3a8e 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -2006,7 +2006,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
if ((p->family == AF_INET) &&
(!bgp_subgrp_multiaccess_check_v4(
piattr->nexthop,
- subgrp)))
+ subgrp, from)))
subgroup_announce_reset_nhop(
(peer_cap_enhe(peer, afi, safi)
? AF_INET6
@@ -2016,7 +2016,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi,
if ((p->family == AF_INET6) &&
(!bgp_subgrp_multiaccess_check_v6(
piattr->mp_nexthop_global,
- subgrp)))
+ subgrp, from)))
subgroup_announce_reset_nhop(
(peer_cap_enhe(peer, afi, safi)
? AF_INET6
@@ -2107,6 +2107,7 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
if (debug)
prefix2str(&rn->p, pfx_buf, sizeof(pfx_buf));
+ rn->reason = bgp_path_selection_none;
/* bgp deterministic-med */
new_select = NULL;
if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
@@ -2186,6 +2187,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
new_select = NULL;
for (pi = bgp_node_get_bgp_path_info(rn);
(pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
+ enum bgp_path_selection_reason reason;
+
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
old_select = pi;
@@ -2226,8 +2229,12 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn,
bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK);
+ reason = rn->reason;
if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
debug, pfx_buf, afi, safi, &rn->reason)) {
+ if (new_select == NULL &&
+ reason != bgp_path_selection_none)
+ rn->reason = reason;
new_select = pi;
}
}
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 52b5402737..029570df35 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -2830,6 +2830,57 @@ static const struct route_map_rule_cmd route_match_ipv6_next_hop_cmd = {
route_match_ipv6_next_hop_free
};
+/* `match ip next-hop IP_ADDRESS' */
+
+static enum route_map_cmd_result_t
+route_match_ipv4_next_hop(void *rule, const struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ struct in_addr *addr = rule;
+ struct bgp_path_info *path;
+
+ if (type == RMAP_BGP) {
+ path = object;
+
+ if (path->attr->nexthop.s_addr == addr->s_addr ||
+ (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4 &&
+ IPV4_ADDR_SAME(&path->attr->mp_nexthop_global_in, addr)))
+ return RMAP_MATCH;
+
+ return RMAP_NOMATCH;
+ }
+
+ return RMAP_NOMATCH;
+}
+
+static void *route_match_ipv4_next_hop_compile(const char *arg)
+{
+ struct in_addr *address;
+ int ret;
+
+ address = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct in_addr));
+
+ ret = inet_pton(AF_INET, arg, address);
+ if (!ret) {
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, address);
+ return NULL;
+ }
+
+ return address;
+}
+
+static void route_match_ipv4_next_hop_free(void *rule)
+{
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+static const struct route_map_rule_cmd route_match_ipv4_next_hop_cmd = {
+ "ip next-hop address",
+ route_match_ipv4_next_hop,
+ route_match_ipv4_next_hop_compile,
+ route_match_ipv4_next_hop_free
+};
+
/* `match ipv6 address prefix-list PREFIX_LIST' */
static enum route_map_cmd_result_t
@@ -5110,6 +5161,28 @@ DEFUN (no_match_ipv6_next_hop,
RMAP_EVENT_MATCH_DELETED);
}
+DEFPY (match_ipv4_next_hop,
+ match_ipv4_next_hop_cmd,
+ "[no$no] match ip next-hop address [A.B.C.D]",
+ NO_STR
+ MATCH_STR
+ IP_STR
+ "Match IP next-hop address of route\n"
+ "IP address\n"
+ "IP address of next-hop\n")
+{
+ int idx_ipv4 = 4;
+
+ if (no)
+ return bgp_route_match_delete(vty, "ip next-hop address", NULL,
+ RMAP_EVENT_MATCH_DELETED);
+
+ if (argv[idx_ipv4]->arg)
+ return bgp_route_match_add(vty, "ip next-hop address",
+ argv[idx_ipv4]->arg,
+ RMAP_EVENT_MATCH_ADDED);
+ return CMD_SUCCESS;
+}
DEFUN (set_ipv6_nexthop_peer,
set_ipv6_nexthop_peer_cmd,
@@ -5563,6 +5636,7 @@ void bgp_route_map_init(void)
route_map_install_match(&route_match_ipv6_address_cmd);
route_map_install_match(&route_match_ipv6_next_hop_cmd);
+ route_map_install_match(&route_match_ipv4_next_hop_cmd);
route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
route_map_install_set(&route_set_ipv6_nexthop_global_cmd);
@@ -5572,6 +5646,7 @@ void bgp_route_map_init(void)
install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
install_element(RMAP_NODE, &no_match_ipv6_next_hop_cmd);
+ install_element(RMAP_NODE, &match_ipv4_next_hop_cmd);
install_element(RMAP_NODE, &set_ipv6_nexthop_global_cmd);
install_element(RMAP_NODE, &no_set_ipv6_nexthop_global_cmd);
install_element(RMAP_NODE, &set_ipv6_nexthop_prefer_global_cmd);
diff --git a/doc/user/routemap.rst b/doc/user/routemap.rst
index 472e2c53ff..f557cbe022 100644
--- a/doc/user/routemap.rst
+++ b/doc/user/routemap.rst
@@ -151,10 +151,15 @@ Route Map Match Command
Matches the specified `prefix-len`. This is a Zebra specific command.
-.. index:: match ip next-hop IPV4_ADDR
-.. clicmd:: match ip next-hop IPV4_ADDR
+.. index:: match ip next-hop address IPV4_ADDR
+.. clicmd:: match ip next-hop address IPV4_ADDR
- Matches the specified `ipv4_addr`.
+ This is a BGP specific match command. Matches the specified `ipv4_addr`.
+
+.. index:: match ipv6 next-hop IPV6_ADDR
+.. clicmd:: match ipv6 next-hop IPV6_ADDR
+
+ This is a BGP specific match command. Matches the specified `ipv6_addr`.
.. index:: match as-path AS_PATH
.. clicmd:: match as-path AS_PATH
diff --git a/libyang b/libyang
new file mode 160000
+Subproject 4241fbbe72216ae2b84f10d25acb1bc84eb967e
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index af25d930d1..8bfad8ee27 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -1520,6 +1520,10 @@ static void pim_show_interface_traffic(struct pim_instance *pim,
pim_ifp->pim_ifstat_join_recv);
json_object_int_add(json_row, "joinTx",
pim_ifp->pim_ifstat_join_send);
+ json_object_int_add(json_row, "pruneTx",
+ pim_ifp->pim_ifstat_prune_send);
+ json_object_int_add(json_row, "pruneRx",
+ pim_ifp->pim_ifstat_prune_recv);
json_object_int_add(json_row, "registerRx",
pim_ifp->pim_ifstat_reg_recv);
json_object_int_add(json_row, "registerTx",
diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c
index 355aa07048..a9f1d9335a 100644
--- a/pimd/pim_rp.c
+++ b/pimd/pim_rp.c
@@ -1294,10 +1294,16 @@ void pim_rp_show_information(struct pim_instance *pim, struct vty *vty, bool uj)
json_row, "outboundInterface",
rp_info->rp.source_nexthop
.interface->name);
-
+ else
+ json_object_string_add(
+ json_row, "outboundInterface",
+ "Unknown");
if (rp_info->i_am_rp)
json_object_boolean_true_add(json_row,
"iAmRP");
+ else
+ json_object_boolean_false_add(json_row,
+ "iAmRP");
if (rp_info->plist)
json_object_string_add(json_row,