summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_attr.c17
-rw-r--r--bgpd/bgp_attr.h18
-rw-r--r--bgpd/bgp_bmp.c6
-rw-r--r--bgpd/bgp_conditional_adv.c8
-rw-r--r--bgpd/bgp_evpn.c5
-rw-r--r--bgpd/bgp_fsm.c73
-rw-r--r--bgpd/bgp_io.c6
-rw-r--r--bgpd/bgp_nexthop.c13
-rw-r--r--bgpd/bgp_nexthop.h5
-rw-r--r--bgpd/bgp_route.c74
-rw-r--r--bgpd/bgp_route.h11
-rw-r--r--bgpd/bgp_routemap.c158
-rw-r--r--bgpd/bgp_routemap_nb.c21
-rw-r--r--bgpd/bgp_routemap_nb.h12
-rw-r--r--bgpd/bgp_routemap_nb_config.c156
-rw-r--r--bgpd/bgp_updgrp_adv.c4
-rw-r--r--bgpd/bgp_vty.c11
-rw-r--r--bgpd/rfapi/rfapi.c12
-rw-r--r--bgpd/rfapi/vnc_export_bgp.c22
-rw-r--r--doc/user/routemap.rst13
-rw-r--r--isisd/isis_vty_fabricd.c10
-rw-r--r--ldpd/ldpe.c2
-rw-r--r--lib/command.h2
-rw-r--r--lib/defun_lex.l3
-rw-r--r--lib/netns_linux.c2
-rw-r--r--lib/ntop.c13
-rw-r--r--lib/ptm_lib.c26
-rw-r--r--lib/routemap.h1
-rw-r--r--lib/routemap_cli.c44
-rw-r--r--lib/routemap_northbound.c42
-rw-r--r--lib/zclient.c2
-rw-r--r--lib/zclient.h61
-rw-r--r--lib/zlog_5424_cli.c1
-rw-r--r--ospfd/ospf_lsa.c17
-rw-r--r--ospfd/ospf_lsa.h149
-rw-r--r--ospfd/ospf_vty.c7
-rw-r--r--pimd/pim6_mld.c2
-rw-r--r--pimd/pim_autorp.c2
-rw-r--r--pimd/pim_bsr_rpdb.c3
-rw-r--r--pimd/pim_zlookup.c2
-rw-r--r--staticd/static_zebra.c2
-rw-r--r--tests/isisd/test_fuzz_isis_tlv_tests.h.gzbin221875 -> 221883 bytes
-rw-r--r--tests/topotests/bfd_isis_topo1/rt1/step1/show_ipv6_route.ref16
-rw-r--r--tests/topotests/bfd_isis_topo1/rt1/step3/show_ipv6_route_healthy.ref16
-rw-r--r--tests/topotests/bfd_isis_topo1/rt1/step3/show_ipv6_route_rt2_down.ref16
-rw-r--r--tests/topotests/bfd_isis_topo1/rt1/step3/show_ipv6_route_rt3_down.ref16
-rw-r--r--tests/topotests/bfd_isis_topo1/rt1/zebra.conf2
-rw-r--r--tests/topotests/bfd_isis_topo1/rt2/zebra.conf2
-rw-r--r--tests/topotests/bfd_isis_topo1/rt3/zebra.conf2
-rw-r--r--tests/topotests/bfd_isis_topo1/rt4/zebra.conf2
-rw-r--r--tests/topotests/bfd_isis_topo1/rt5/zebra.conf2
-rw-r--r--tests/topotests/bfd_ospf_topo1/rt1/step1/show_ipv6_route.ref16
-rw-r--r--tests/topotests/bfd_ospf_topo1/rt1/step3/show_ipv6_route_healthy.ref16
-rw-r--r--tests/topotests/bfd_ospf_topo1/rt1/step3/show_ipv6_route_rt2_down.ref16
-rw-r--r--tests/topotests/bfd_ospf_topo1/rt1/step3/show_ipv6_route_rt3_down.ref16
-rw-r--r--tests/topotests/bfd_ospf_topo1/rt1/zebra.conf2
-rw-r--r--tests/topotests/bfd_ospf_topo1/rt2/zebra.conf2
-rw-r--r--tests/topotests/bfd_ospf_topo1/rt3/zebra.conf2
-rw-r--r--tests/topotests/bfd_ospf_topo1/rt4/zebra.conf2
-rw-r--r--tests/topotests/bfd_ospf_topo1/rt5/zebra.conf2
-rw-r--r--tests/topotests/bgp_aigp/r1/bgpd.conf16
-rw-r--r--tests/topotests/bgp_aigp/r1/ospfd.conf2
-rw-r--r--tests/topotests/bgp_aigp/r1/zebra.conf3
-rw-r--r--tests/topotests/bgp_aigp/r2/bgpd.conf2
-rw-r--r--tests/topotests/bgp_aigp/r2/ospfd.conf2
-rw-r--r--tests/topotests/bgp_aigp/r3/bgpd.conf2
-rw-r--r--tests/topotests/bgp_aigp/r3/ospfd.conf2
-rw-r--r--tests/topotests/bgp_aigp/r4/bgpd.conf23
-rw-r--r--tests/topotests/bgp_aigp/r4/ospfd.conf2
-rw-r--r--tests/topotests/bgp_aigp/r5/bgpd.conf16
-rw-r--r--tests/topotests/bgp_aigp/r5/ospfd.conf2
-rw-r--r--tests/topotests/bgp_aigp/r6/bgpd.conf8
-rw-r--r--tests/topotests/bgp_aigp/r6/ospfd.conf2
-rw-r--r--tests/topotests/bgp_aigp/r6/zebra.conf1
-rw-r--r--tests/topotests/bgp_aigp/r8/bgpd.conf4
-rw-r--r--tests/topotests/bgp_aigp/r8/zebra.conf4
-rw-r--r--tests/topotests/bgp_aigp/test_bgp_aigp.py125
-rw-r--r--tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py6
-rw-r--r--tests/topotests/bgp_ipv4_over_ipv6/test_rfc5549_ebgp_unnumbered_nbr.py4
-rw-r--r--tests/topotests/bgp_match_peer/r1/frr.conf6
-rw-r--r--tests/topotests/bgp_match_peer/test_bgp_match_peer.py23
-rw-r--r--tests/topotests/bgp_nexthop_ipv6/r4/show_bgp_ipv6_step2.json48
-rw-r--r--tests/topotests/bgp_nexthop_ipv6/r5/show_bgp_ipv6_step2.json48
-rw-r--r--tests/topotests/bgp_set_metric_igp/__init__.py0
-rw-r--r--tests/topotests/bgp_set_metric_igp/r1/frr.conf13
-rw-r--r--tests/topotests/bgp_set_metric_igp/r2/frr.conf36
-rw-r--r--tests/topotests/bgp_set_metric_igp/r3/frr.conf38
-rw-r--r--tests/topotests/bgp_set_metric_igp/r4/frr.conf41
-rw-r--r--tests/topotests/bgp_set_metric_igp/r5/frr.conf14
-rw-r--r--tests/topotests/bgp_set_metric_igp/test_bgp_set_metric_igp.py146
-rw-r--r--tests/topotests/lib/common_check.py2
-rw-r--r--tools/gcc-plugins/frr-format.c3
-rw-r--r--vtysh/vtysh.c12
-rw-r--r--vtysh/vtysh_main.c5
-rw-r--r--yang/frr-bgp-route-map.yang37
-rw-r--r--yang/frr-route-map.yang16
-rw-r--r--zebra/connected.c40
-rw-r--r--zebra/dpdk/zebra_dplane_dpdk.c2
-rw-r--r--zebra/dplane_fpm_nl.c1
-rw-r--r--zebra/if_netlink.c136
-rw-r--r--zebra/ipforward_proc.c16
-rw-r--r--zebra/kernel_netlink.c15
-rw-r--r--zebra/kernel_socket.c1
-rw-r--r--zebra/main.c4
-rw-r--r--zebra/zapi_msg.c8
-rw-r--r--zebra/zebra_dplane.c231
-rw-r--r--zebra/zebra_dplane.h32
-rw-r--r--zebra/zebra_l2.h11
-rw-r--r--zebra/zebra_nb_state.c1
-rw-r--r--zebra/zebra_netns_id.c20
-rw-r--r--zebra/zebra_netns_notify.c11
-rw-r--r--zebra/zebra_ns.c20
-rw-r--r--zebra/zebra_ns.h2
-rw-r--r--zebra/zebra_rib.c71
-rw-r--r--zebra/zebra_rnh.c11
-rw-r--r--zebra/zebra_script.c1
-rw-r--r--zebra/zebra_srte.c4
-rw-r--r--zebra/zebra_vxlan.c111
-rw-r--r--zebra/zebra_vxlan.h2
119 files changed, 1822 insertions, 829 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 7cdf98cba7..596d820f1b 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -480,16 +480,6 @@ static bool bgp_attr_aigp_get_tlv_metric(uint8_t *pnt, int length,
return false;
}
-static uint64_t bgp_aigp_metric_total(struct bgp_path_info *bpi)
-{
- uint64_t aigp = bgp_attr_get_aigp_metric(bpi->attr);
-
- if (bpi->nexthop)
- return aigp + bpi->nexthop->metric;
- else
- return aigp;
-}
-
static void stream_put_bgp_aigp_tlv_metric(struct stream *s,
struct bgp_path_info *bpi)
{
@@ -1187,8 +1177,7 @@ struct attr *bgp_attr_aggregate_intern(
SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_ORIGIN));
/* MED */
- attr.med = 0;
- SET_FLAG(attr.flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
+ bgp_attr_set_med(&attr, 0);
/* AS path attribute. */
if (aspath)
@@ -1943,9 +1932,7 @@ static enum bgp_attr_parse_ret bgp_attr_med(struct bgp_attr_parser_args *args)
args->total);
}
- attr->med = stream_getl(peer->curr);
-
- SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
+ bgp_attr_set_med(attr, stream_getl(peer->curr));
return BGP_ATTR_PARSE_PROCEED;
}
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index a8ca8c1fa6..0a43399be6 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -593,9 +593,23 @@ static inline uint64_t bgp_attr_get_aigp_metric(const struct attr *attr)
static inline void bgp_attr_set_aigp_metric(struct attr *attr, uint64_t aigp)
{
attr->aigp_metric = aigp;
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP));
+}
+
+static inline uint64_t bgp_aigp_metric_total(struct bgp_path_info *bpi)
+{
+ uint64_t aigp = bgp_attr_get_aigp_metric(bpi->attr);
- if (aigp)
- SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP));
+ if (bpi->nexthop)
+ return aigp + bpi->nexthop->metric;
+ else
+ return aigp;
+}
+
+static inline void bgp_attr_set_med(struct attr *attr, uint32_t med)
+{
+ attr->med = med;
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC));
}
static inline struct cluster_list *bgp_attr_get_cluster(const struct attr *attr)
diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c
index 08f8b8b734..59efb35235 100644
--- a/bgpd/bgp_bmp.c
+++ b/bgpd/bgp_bmp.c
@@ -489,7 +489,7 @@ static struct stream *bmp_peerstate(struct peer *peer, bool down)
&uptime_real);
/* Local Address (16 bytes) */
- if (!peer->su_local || is_locrib)
+ if (is_locrib)
stream_put(s, 0, 16);
else if (peer->su_local->sa.sa_family == AF_INET6)
stream_put(s, &peer->su_local->sin6.sin6_addr, 16);
@@ -501,14 +501,14 @@ static struct stream *bmp_peerstate(struct peer *peer, bool down)
}
/* Local Port, Remote Port */
- if (is_locrib)
+ if (!peer->su_local || is_locrib)
stream_putw(s, 0);
else if (peer->su_local->sa.sa_family == AF_INET6)
stream_putw(s, htons(peer->su_local->sin6.sin6_port));
else if (peer->su_local->sa.sa_family == AF_INET)
stream_putw(s, htons(peer->su_local->sin.sin_port));
- if (is_locrib)
+ if (!peer->su_remote || is_locrib)
stream_putw(s, 0);
else if (peer->su_remote->sa.sa_family == AF_INET6)
stream_putw(s, htons(peer->su_remote->sin6.sin6_port));
diff --git a/bgpd/bgp_conditional_adv.c b/bgpd/bgp_conditional_adv.c
index 2d96b444b6..a99d0201e7 100644
--- a/bgpd/bgp_conditional_adv.c
+++ b/bgpd/bgp_conditional_adv.c
@@ -30,8 +30,8 @@ bgp_check_rmap_prefixes_in_bgp_table(struct bgp_table *table,
dummy_attr = *pi->attr;
/* Fill temp path_info */
- prep_for_rmap_apply(&path, &path_extra, dest, pi,
- pi->peer, &dummy_attr);
+ prep_for_rmap_apply(&path, &path_extra, dest, pi, pi->peer, NULL,
+ &dummy_attr);
RESET_FLAG(dummy_attr.rmap_change_flags);
@@ -99,8 +99,8 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi,
advmap_attr = *pi->attr;
/* Fill temp path_info */
- prep_for_rmap_apply(&path, &path_extra, dest, pi,
- pi->peer, &advmap_attr);
+ prep_for_rmap_apply(&path, &path_extra, dest, pi, pi->peer, NULL,
+ &advmap_attr);
RESET_FLAG(advmap_attr.rmap_change_flags);
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 0a8ce61548..ad29828ade 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -5392,9 +5392,8 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi,
tmp_attr = *pi->attr;
/* Fill temp path_info */
- prep_for_rmap_apply(&tmp_pi, &tmp_pie,
- dest, pi, pi->peer,
- &tmp_attr);
+ prep_for_rmap_apply(&tmp_pi, &tmp_pie, dest, pi, pi->peer,
+ NULL, &tmp_attr);
RESET_FLAG(tmp_attr.rmap_change_flags);
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index cdd9b7ae4d..567af5bb75 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -2776,99 +2776,72 @@ int bgp_gr_update_all(struct bgp *bgp, enum global_gr_command global_gr_cmd)
const char *print_peer_gr_mode(enum peer_mode pr_mode)
{
- const char *peer_gr_mode = NULL;
-
switch (pr_mode) {
case PEER_HELPER:
- peer_gr_mode = "PEER_HELPER";
- break;
+ return "PEER_HELPER";
case PEER_GR:
- peer_gr_mode = "PEER_GR";
- break;
+ return "PEER_GR";
case PEER_DISABLE:
- peer_gr_mode = "PEER_DISABLE";
- break;
+ return "PEER_DISABLE";
case PEER_INVALID:
- peer_gr_mode = "PEER_INVALID";
- break;
+ return "PEER_INVALID";
case PEER_GLOBAL_INHERIT:
- peer_gr_mode = "PEER_GLOBAL_INHERIT";
- break;
+ return "PEER_GLOBAL_INHERIT";
}
- return peer_gr_mode;
+ return NULL;
}
const char *print_peer_gr_cmd(enum peer_gr_command pr_gr_cmd)
{
- const char *peer_gr_cmd = NULL;
-
switch (pr_gr_cmd) {
case PEER_GR_CMD:
- peer_gr_cmd = "PEER_GR_CMD";
- break;
+ return "PEER_GR_CMD";
case NO_PEER_GR_CMD:
- peer_gr_cmd = "NO_PEER_GR_CMD";
- break;
+ return "NO_PEER_GR_CMD";
case PEER_DISABLE_CMD:
- peer_gr_cmd = "PEER_DISABLE_GR_CMD";
- break;
+ return "PEER_DISABLE_GR_CMD";
case NO_PEER_DISABLE_CMD:
- peer_gr_cmd = "NO_PEER_DISABLE_GR_CMD";
- break;
+ return "NO_PEER_DISABLE_GR_CMD";
case PEER_HELPER_CMD:
- peer_gr_cmd = "PEER_HELPER_CMD";
- break;
+ return "PEER_HELPER_CMD";
case NO_PEER_HELPER_CMD:
- peer_gr_cmd = "NO_PEER_HELPER_CMD";
- break;
+ return "NO_PEER_HELPER_CMD";
}
- return peer_gr_cmd;
+ return NULL;
}
const char *print_global_gr_mode(enum global_mode gl_mode)
{
- const char *global_gr_mode = "???";
-
switch (gl_mode) {
case GLOBAL_HELPER:
- global_gr_mode = "GLOBAL_HELPER";
- break;
+ return "GLOBAL_HELPER";
case GLOBAL_GR:
- global_gr_mode = "GLOBAL_GR";
- break;
+ return "GLOBAL_GR";
case GLOBAL_DISABLE:
- global_gr_mode = "GLOBAL_DISABLE";
- break;
+ return "GLOBAL_DISABLE";
case GLOBAL_INVALID:
- global_gr_mode = "GLOBAL_INVALID";
- break;
+ return "GLOBAL_INVALID";
}
- return global_gr_mode;
+ return "???";
}
const char *print_global_gr_cmd(enum global_gr_command gl_gr_cmd)
{
- const char *global_gr_cmd = NULL;
-
switch (gl_gr_cmd) {
case GLOBAL_GR_CMD:
- global_gr_cmd = "GLOBAL_GR_CMD";
- break;
+ return "GLOBAL_GR_CMD";
case NO_GLOBAL_GR_CMD:
- global_gr_cmd = "NO_GLOBAL_GR_CMD";
- break;
+ return "NO_GLOBAL_GR_CMD";
case GLOBAL_DISABLE_CMD:
- global_gr_cmd = "GLOBAL_DISABLE_CMD";
- break;
+ return "GLOBAL_DISABLE_CMD";
case NO_GLOBAL_DISABLE_CMD:
- global_gr_cmd = "NO_GLOBAL_DISABLE_CMD";
- break;
+ return "NO_GLOBAL_DISABLE_CMD";
}
- return global_gr_cmd;
+ return NULL;
}
enum global_mode bgp_global_gr_mode_get(struct bgp *bgp)
diff --git a/bgpd/bgp_io.c b/bgpd/bgp_io.c
index b07e69ac31..9e9251c854 100644
--- a/bgpd/bgp_io.c
+++ b/bgpd/bgp_io.c
@@ -512,7 +512,13 @@ static uint16_t bgp_read(struct peer_connection *connection, int *code_p)
readsize = MIN(ibuf_work_space, sizeof(ibuf_scratch));
+#ifdef __clang_analyzer__
+ /* clang-SA doesn't want you to call read() while holding a mutex */
+ (void)readsize;
+ nbytes = 0;
+#else
nbytes = read(connection->fd, ibuf_scratch, readsize);
+#endif
/* EAGAIN or EWOULDBLOCK; come back later */
if (nbytes < 0 && ERRNO_IO_RETRY(errno)) {
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index 564ad118eb..401549c4e8 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -1377,16 +1377,9 @@ char *bgp_nexthop_dump_bnc_change_flags(struct bgp_nexthop_cache *bnc,
return buf;
}
- snprintfrr(buf, len, "%s%s%s",
- CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED)
- ? "Changed "
- : "",
- CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED)
- ? "Metric "
- : "",
- CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CONNECTED_CHANGED)
- ? "Connected "
- : "");
+ snprintfrr(buf, len, "%s%s",
+ CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED) ? "Changed " : "",
+ CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED) ? "Metric " : "");
return buf;
}
diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h
index 5014eb8f34..6a4a02dcc8 100644
--- a/bgpd/bgp_nexthop.h
+++ b/bgpd/bgp_nexthop.h
@@ -45,11 +45,10 @@ struct bgp_nexthop_cache {
*/
bool is_evpn_gwip_nexthop;
- uint16_t change_flags;
+ uint8_t change_flags;
#define BGP_NEXTHOP_CHANGED (1 << 0)
#define BGP_NEXTHOP_METRIC_CHANGED (1 << 1)
-#define BGP_NEXTHOP_CONNECTED_CHANGED (1 << 2)
-#define BGP_NEXTHOP_MACIP_CHANGED (1 << 3)
+#define BGP_NEXTHOP_MACIP_CHANGED (1 << 2)
struct nexthop *nexthop;
time_t last_update;
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 9cefec0706..ed1dbc6b42 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -1068,8 +1068,8 @@ int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
if (CHECK_FLAG(newattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
CHECK_FLAG(existattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) &&
CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_AIGP)) {
- uint64_t new_aigp = bgp_attr_get_aigp_metric(newattr);
- uint64_t exist_aigp = bgp_attr_get_aigp_metric(existattr);
+ uint64_t new_aigp = bgp_aigp_metric_total(new);
+ uint64_t exist_aigp = bgp_aigp_metric_total(exist);
if (new_aigp < exist_aigp) {
*reason = bgp_path_selection_aigp;
@@ -2148,7 +2148,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
struct attr *piattr;
route_map_result_t ret;
int transparent;
- int reflect;
+ int ibgp_to_ibgp;
afi_t afi;
safi_t safi;
int samepeer_safe = 0; /* for synthetic mplsvpns routes */
@@ -2357,14 +2357,14 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
}
}
- /* Route-Reflect check. */
+ /* iBGP to iBGP check. */
if (from->sort == BGP_PEER_IBGP && peer->sort == BGP_PEER_IBGP)
- reflect = 1;
+ ibgp_to_ibgp = 1;
else
- reflect = 0;
+ ibgp_to_ibgp = 0;
/* IBGP reflection check. */
- if (reflect && !samepeer_safe) {
+ if (ibgp_to_ibgp && !samepeer_safe) {
/* A route from a Client peer. */
if (CHECK_FLAG(from->af_flags[afi][safi],
PEER_FLAG_REFLECTOR_CLIENT)) {
@@ -2410,8 +2410,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
/* If originator-id is not set and the route is to be reflected,
set the originator id */
- if (reflect
- && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
+ if (ibgp_to_ibgp && (!(attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)))) {
IPV4_ADDR_COPY(&(attr->originator_id), &(from->remote_id));
SET_FLAG(attr->flag, BGP_ATTR_ORIGINATOR_ID);
}
@@ -2444,7 +2443,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
* announced to an EBGP peer (and they have the same attributes barring
* their nexthop).
*/
- if (reflect)
+ if (ibgp_to_ibgp)
SET_FLAG(attr->rmap_change_flags, BATTR_REFLECTED);
#define NEXTHOP_IS_V6 \
@@ -2472,7 +2471,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
*/
if (IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local))
global_and_ll = true;
- } else if (!reflect && !transparent &&
+ } else if (!ibgp_to_ibgp && !transparent &&
+ !CHECK_FLAG(from->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT) &&
IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_local) && peer->shared_network &&
(from == bgp->peer_self || peer->sort == BGP_PEER_EBGP))
global_and_ll = true;
@@ -2512,8 +2512,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
struct attr dummy_attr = *attr;
/* Fill temp path_info */
- prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
- pi, peer, &dummy_attr);
+ prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest, pi, peer, NULL,
+ &dummy_attr);
struct route_map *amap =
route_map_lookup_by_name(filter->advmap.aname);
@@ -2537,9 +2537,13 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
struct bgp_path_info_extra dummy_rmap_path_extra = {0};
struct attr dummy_attr = {0};
- /* Fill temp path_info */
- prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
- pi, peer, attr);
+ /* Fill temp path_info.
+ * Inject the peer structure of the source peer (from).
+ * This is useful for e.g. `match peer ...` in outgoing
+ * direction.
+ */
+ prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest, pi, peer, from, attr);
+
/*
* The route reflector is not allowed to modify the attributes
* of the reflected IBGP routes unless explicitly allowed.
@@ -2694,9 +2698,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
PEER_FLAG_NEXTHOP_SELF)
|| CHECK_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_FORCE_NEXTHOP_SELF)) {
- if (!reflect
- || CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_FORCE_NEXTHOP_SELF)) {
+ if (!ibgp_to_ibgp ||
+ CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_FORCE_NEXTHOP_SELF)) {
subgroup_announce_reset_nhop(
(peer_cap_enhe(peer, afi, safi)
? AF_INET6
@@ -3427,9 +3430,8 @@ static void bgp_process_evpn_route_injection(struct bgp *bgp, afi_t afi,
dummy_attr = *new_select->attr;
/* Fill temp path_info */
- prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest,
- new_select, new_select->peer,
- &dummy_attr);
+ prep_for_rmap_apply(&rmap_path, &rmap_path_extra, dest, new_select,
+ new_select->peer, NULL, &dummy_attr);
RESET_FLAG(dummy_attr.rmap_change_flags);
@@ -3727,11 +3729,10 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
/* If there is a change of interest to peers, reannounce the
* route. */
- if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
- || CHECK_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG)
- || CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED)) {
+ if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED) ||
+ CHECK_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED) ||
+ bgp_zebra_has_route_changed(old_select)) {
group_announce_route(bgp, afi, safi, dest, new_select);
-
/* unicast routes must also be annouced to
* labeled-unicast update-groups */
if (safi == SAFI_UNICAST)
@@ -6747,15 +6748,12 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
bgp_attr_default_set(&attr, bgp, BGP_ORIGIN_IGP);
attr.nexthop = bgp_static->igpnexthop;
- attr.med = bgp_static->igpmetric;
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
+
+ bgp_attr_set_med(&attr, bgp_static->igpmetric);
if (afi == AFI_IP)
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
- if (bgp_static->igpmetric)
- bgp_attr_set_aigp_metric(&attr, bgp_static->igpmetric);
-
if (bgp_static->atomic)
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
@@ -9015,14 +9013,10 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
else
UNSET_FLAG(attr.nh_flags, BGP_ATTR_NH_IF_OPERSTATE);
- attr.med = metric;
+ bgp_attr_set_med(&attr, metric);
attr.distance = distance;
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
attr.tag = tag;
- if (metric)
- bgp_attr_set_aigp_metric(&attr, metric);
-
afi = family2afi(p->family);
red = bgp_redist_lookup(bgp, afi, type, instance);
@@ -9032,10 +9026,8 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
/* Copy attribute for modification. */
attr_new = attr;
- if (red->redist_metric_flag) {
+ if (red->redist_metric_flag)
attr_new.med = red->redist_metric;
- bgp_attr_set_aigp_metric(&attr_new, red->redist_metric);
- }
/* Apply route-map. */
if (red->rmap.name) {
@@ -11787,8 +11779,8 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t sa
dummy_attr = *pi->attr;
- prep_for_rmap_apply(&path, &extra, dest, pi,
- pi->peer, &dummy_attr);
+ prep_for_rmap_apply(&path, &extra, dest, pi, pi->peer, NULL,
+ &dummy_attr);
ret = route_map_apply(rmap, dest_p, &path);
bgp_attr_flush(&dummy_attr);
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index d71bfd3ebc..1df0ffd300 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -284,6 +284,9 @@ struct bgp_path_info {
/* Peer structure. */
struct peer *peer;
+ /* From peer structure */
+ struct peer *from;
+
/* Attribute structure. */
struct attr *attr;
@@ -619,13 +622,13 @@ static inline bool is_pi_family_matching(struct bgp_path_info *pi,
}
static inline void prep_for_rmap_apply(struct bgp_path_info *dst_pi,
- struct bgp_path_info_extra *dst_pie,
- struct bgp_dest *dest,
- struct bgp_path_info *src_pi,
- struct peer *peer, struct attr *attr)
+ struct bgp_path_info_extra *dst_pie, struct bgp_dest *dest,
+ struct bgp_path_info *src_pi, struct peer *peer,
+ struct peer *from, struct attr *attr)
{
memset(dst_pi, 0, sizeof(struct bgp_path_info));
dst_pi->peer = peer;
+ dst_pi->from = from;
dst_pi->attr = attr;
dst_pi->net = dest;
dst_pi->flags = src_pi->flags;
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 4900bb3ce3..8dd48575e5 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -125,6 +125,10 @@ o Local extensions
#define RMAP_VALUE_ADD 1
#define RMAP_VALUE_SUB 2
+#define RMAP_VALUE_TYPE_RTT 1
+#define RMAP_VALUE_TYPE_IGP 2
+#define RMAP_VALUE_TYPE_AIGP 3
+
struct rmap_value {
uint8_t action;
uint8_t variable;
@@ -140,14 +144,21 @@ static int route_value_match(struct rmap_value *rv, uint32_t value)
}
static uint32_t route_value_adjust(struct rmap_value *rv, uint32_t current,
- struct peer *peer)
+ struct bgp_path_info *bpi)
{
uint32_t value;
+ struct peer *peer = bpi->peer;
switch (rv->variable) {
- case 1:
+ case RMAP_VALUE_TYPE_RTT:
value = peer->rtt;
break;
+ case RMAP_VALUE_TYPE_IGP:
+ value = bpi->extra ? bpi->extra->igpmetric : 0;
+ break;
+ case RMAP_VALUE_TYPE_AIGP:
+ value = MIN(bpi->attr->aigp_metric, UINT32_MAX);
+ break;
default:
value = rv->value;
break;
@@ -187,11 +198,14 @@ static void *route_value_compile(const char *arg)
larg = strtoul(arg, &endptr, 10);
if (*arg == 0 || *endptr != 0 || errno || larg > UINT32_MAX)
return NULL;
+ } else if (strmatch(arg, "rtt")) {
+ var = RMAP_VALUE_TYPE_RTT;
+ } else if (strmatch(arg, "igp")) {
+ var = RMAP_VALUE_TYPE_IGP;
+ } else if (strmatch(arg, "aigp")) {
+ var = RMAP_VALUE_TYPE_AIGP;
} else {
- if (strcmp(arg, "rtt") == 0)
- var = 1;
- else
- return NULL;
+ return NULL;
}
rv = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(struct rmap_value));
@@ -333,6 +347,66 @@ static const struct route_map_rule_cmd route_match_peer_cmd = {
route_match_peer_free
};
+static enum route_map_cmd_result_t route_match_src_peer(void *rule, const struct prefix *prefix,
+ void *object)
+{
+ struct bgp_match_peer_compiled *pc;
+ union sockunion *su;
+ struct peer_group *group;
+ struct peer *peer;
+ struct listnode *node, *nnode;
+ struct bgp_path_info *bpi;
+
+ pc = rule;
+ su = &pc->su;
+ bpi = object;
+ peer = bpi->from;
+
+ /* Fallback to destination (current) peer. This is mostly
+ * happens if `match src-peer ...` is used at incoming direction.
+ */
+ if (!peer)
+ peer = bpi->peer;
+
+ if (!peer)
+ return RMAP_NOMATCH;
+
+ if (pc->interface) {
+ if (!peer->conf_if && !peer->group)
+ return RMAP_NOMATCH;
+
+ if (peer->conf_if && strcmp(peer->conf_if, pc->interface) == 0)
+ return RMAP_MATCH;
+
+ if (peer->group && strcmp(peer->group->name, pc->interface) == 0)
+ return RMAP_MATCH;
+
+ return RMAP_NOMATCH;
+ }
+
+ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ if (sockunion_same(su, &peer->connection->su))
+ return RMAP_MATCH;
+
+ return RMAP_NOMATCH;
+ }
+
+ group = peer->group;
+ for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
+ if (sockunion_same(su, &peer->connection->su))
+ return RMAP_MATCH;
+ }
+
+ return RMAP_NOMATCH;
+}
+
+static const struct route_map_rule_cmd route_match_src_peer_cmd = {
+ "src-peer",
+ route_match_src_peer,
+ route_match_peer_compile,
+ route_match_peer_free
+};
+
#ifdef HAVE_SCRIPTING
enum frrlua_rm_status {
@@ -2145,7 +2219,7 @@ route_set_local_pref(void *rule, const struct prefix *prefix, void *object)
locpref = path->attr->local_pref;
path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
- path->attr->local_pref = route_value_adjust(rv, locpref, path->peer);
+ path->attr->local_pref = route_value_adjust(rv, locpref, path);
return RMAP_OKAY;
}
@@ -2172,7 +2246,7 @@ route_set_weight(void *rule, const struct prefix *prefix, void *object)
path = object;
/* Set weight value. */
- path->attr->weight = route_value_adjust(rv, 0, path->peer);
+ path->attr->weight = route_value_adjust(rv, 0, path);
return RMAP_OKAY;
}
@@ -2222,8 +2296,7 @@ route_set_metric(void *rule, const struct prefix *prefix, void *object)
if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
med = path->attr->med;
- path->attr->med = route_value_adjust(rv, med, path->peer);
- path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
+ bgp_attr_set_med(path->attr, route_value_adjust(rv, med, path));
return RMAP_OKAY;
}
@@ -3451,19 +3524,15 @@ route_set_aigp_metric(void *rule, const struct prefix *pfx, void *object)
{
const char *aigp_metric = rule;
struct bgp_path_info *path = object;
- uint32_t aigp = 0;
-
- if (strmatch(aigp_metric, "igp-metric")) {
- if (!path->nexthop)
- return RMAP_NOMATCH;
+ uint32_t aigp;
- bgp_attr_set_aigp_metric(path->attr, path->nexthop->metric);
- } else {
+ /* Note: the metric is stored as MED for a locally redistributed. */
+ if (strmatch(aigp_metric, "igp-metric"))
+ aigp = path->nexthop ? path->nexthop->metric : path->attr->med;
+ else
aigp = atoi(aigp_metric);
- bgp_attr_set_aigp_metric(path->attr, aigp);
- }
- path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AIGP);
+ bgp_attr_set_aigp_metric(path->attr, aigp);
return RMAP_OKAY;
}
@@ -5274,6 +5343,52 @@ DEFUN_YANG (no_match_peer,
return nb_cli_apply_changes(vty, NULL);
}
+DEFPY_YANG (match_src_peer,
+ match_src_peer_cmd,
+ "match src-peer <A.B.C.D$addrv4|X:X::X:X$addrv6|WORD$intf>",
+ MATCH_STR
+ "Match source peer address\n"
+ "IP address of peer\n"
+ "IPv6 address of peer\n"
+ "Interface name of peer or peer group name\n")
+{
+ const char *xpath = "./match-condition[condition='frr-bgp-route-map:src-peer']";
+ char xpath_value[XPATH_MAXLEN];
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+
+ snprintf(xpath_value, sizeof(xpath_value),
+ "%s/rmap-match-condition/frr-bgp-route-map:src-peer-ipv4-address", xpath);
+ nb_cli_enqueue_change(vty, xpath_value, addrv4_str ? NB_OP_MODIFY : NB_OP_DESTROY,
+ addrv4_str);
+ snprintf(xpath_value, sizeof(xpath_value),
+ "%s/rmap-match-condition/frr-bgp-route-map:src-peer-ipv6-address", xpath);
+ nb_cli_enqueue_change(vty, xpath_value, addrv6_str ? NB_OP_MODIFY : NB_OP_DESTROY,
+ addrv6_str);
+ snprintf(xpath_value, sizeof(xpath_value),
+ "%s/rmap-match-condition/frr-bgp-route-map:src-peer-interface", xpath);
+ nb_cli_enqueue_change(vty, xpath_value, intf ? NB_OP_MODIFY : NB_OP_DESTROY, intf);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFUN_YANG (no_match_src_peer,
+ no_match_src_peer_cmd,
+ "no match src-peer [<A.B.C.D|X:X::X:X|WORD>]",
+ NO_STR
+ MATCH_STR
+ "Match peer address\n"
+ "IP address of peer\n"
+ "IPv6 address of peer\n"
+ "Interface name of peer\n")
+{
+ const char *xpath = "./match-condition[condition='frr-bgp-route-map:src-peer']";
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
#ifdef HAVE_SCRIPTING
DEFUN_YANG (match_script,
match_script_cmd,
@@ -7765,6 +7880,7 @@ void bgp_route_map_init(void)
route_map_no_set_tag_hook(generic_set_delete);
route_map_install_match(&route_match_peer_cmd);
+ route_map_install_match(&route_match_src_peer_cmd);
route_map_install_match(&route_match_alias_cmd);
route_map_install_match(&route_match_local_pref_cmd);
#ifdef HAVE_SCRIPTING
@@ -7832,6 +7948,8 @@ void bgp_route_map_init(void)
install_element(RMAP_NODE, &match_peer_cmd);
install_element(RMAP_NODE, &match_peer_local_cmd);
+ install_element(RMAP_NODE, &match_src_peer_cmd);
+ install_element(RMAP_NODE, &no_match_src_peer_cmd);
install_element(RMAP_NODE, &no_match_peer_cmd);
install_element(RMAP_NODE, &match_ip_route_source_cmd);
install_element(RMAP_NODE, &no_match_ip_route_source_cmd);
diff --git a/bgpd/bgp_routemap_nb.c b/bgpd/bgp_routemap_nb.c
index 096502aaa9..d8fdb4fbc4 100644
--- a/bgpd/bgp_routemap_nb.c
+++ b/bgpd/bgp_routemap_nb.c
@@ -110,6 +110,27 @@ const struct frr_yang_module_info frr_bgp_route_map_info = {
}
},
{
+ .xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:src-peer-ipv4-address",
+ .cbs = {
+ .modify = lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv4_address_modify,
+ .destroy = lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv4_address_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:src-peer-interface",
+ .cbs = {
+ .modify = lib_route_map_entry_match_condition_rmap_match_condition_src_peer_interface_modify,
+ .destroy = lib_route_map_entry_match_condition_rmap_match_condition_src_peer_interface_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:src-peer-ipv6-address",
+ .cbs = {
+ .modify = lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv6_address_modify,
+ .destroy = lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv6_address_destroy,
+ }
+ },
+ {
.xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:list-name",
.cbs = {
.modify = lib_route_map_entry_match_condition_rmap_match_condition_list_name_modify,
diff --git a/bgpd/bgp_routemap_nb.h b/bgpd/bgp_routemap_nb.h
index d7f0cea30e..f59686f386 100644
--- a/bgpd/bgp_routemap_nb.h
+++ b/bgpd/bgp_routemap_nb.h
@@ -46,6 +46,18 @@ int lib_route_map_entry_match_condition_rmap_match_condition_peer_ipv6_address_m
int lib_route_map_entry_match_condition_rmap_match_condition_peer_ipv6_address_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_peer_local_modify(struct nb_cb_modify_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_peer_local_destroy(struct nb_cb_destroy_args *args);
+int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv4_address_modify(
+ struct nb_cb_modify_args *args);
+int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv4_address_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_interface_modify(
+ struct nb_cb_modify_args *args);
+int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_interface_destroy(
+ struct nb_cb_destroy_args *args);
+int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv6_address_modify(
+ struct nb_cb_modify_args *args);
+int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv6_address_destroy(
+ struct nb_cb_destroy_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_access_list_num_modify(struct nb_cb_modify_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_access_list_num_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_access_list_num_extended_modify(struct nb_cb_modify_args *args);
diff --git a/bgpd/bgp_routemap_nb_config.c b/bgpd/bgp_routemap_nb_config.c
index 15c32eaa28..0dca196ed6 100644
--- a/bgpd/bgp_routemap_nb_config.c
+++ b/bgpd/bgp_routemap_nb_config.c
@@ -809,6 +809,162 @@ lib_route_map_entry_match_condition_rmap_match_condition_peer_local_destroy(
}
/*
+ * XPath: /frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:src-peer-ipv4-address
+ */
+int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv4_address_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct routemap_hook_context *rhc;
+ const char *peer;
+ enum rmap_compile_rets ret;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ /* Add configuration. */
+ rhc = nb_running_get_entry(args->dnode, NULL, true);
+ peer = yang_dnode_get_string(args->dnode, NULL);
+
+ /* Set destroy information. */
+ rhc->rhc_mhook = bgp_route_match_delete;
+ rhc->rhc_rule = "src-peer";
+ rhc->rhc_event = RMAP_EVENT_MATCH_DELETED;
+
+ ret = bgp_route_match_add(rhc->rhc_rmi, "src-peer", peer, RMAP_EVENT_MATCH_ADDED,
+ args->errmsg, args->errmsg_len);
+
+ if (ret != RMAP_COMPILE_SUCCESS) {
+ rhc->rhc_mhook = NULL;
+ return NB_ERR_INCONSISTENCY;
+ }
+ }
+
+ return NB_OK;
+}
+
+int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv4_address_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ return lib_route_map_entry_match_destroy(args);
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:src-peer-interface
+ */
+int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_interface_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct routemap_hook_context *rhc;
+ const char *peer;
+ enum rmap_compile_rets ret;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ /* Add configuration. */
+ rhc = nb_running_get_entry(args->dnode, NULL, true);
+ peer = yang_dnode_get_string(args->dnode, NULL);
+
+ /* Set destroy information. */
+ rhc->rhc_mhook = bgp_route_match_delete;
+ rhc->rhc_rule = "src-peer";
+ rhc->rhc_event = RMAP_EVENT_MATCH_DELETED;
+
+ ret = bgp_route_match_add(rhc->rhc_rmi, "src-peer", peer, RMAP_EVENT_MATCH_ADDED,
+ args->errmsg, args->errmsg_len);
+
+ if (ret != RMAP_COMPILE_SUCCESS) {
+ rhc->rhc_mhook = NULL;
+ return NB_ERR_INCONSISTENCY;
+ }
+ }
+
+ return NB_OK;
+}
+
+int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_interface_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ return lib_route_map_entry_match_destroy(args);
+ }
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:src-peer-ipv6-address
+ */
+int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv6_address_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct routemap_hook_context *rhc;
+ const char *peer;
+ enum rmap_compile_rets ret;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ /* Add configuration. */
+ rhc = nb_running_get_entry(args->dnode, NULL, true);
+ peer = yang_dnode_get_string(args->dnode, NULL);
+
+ /* Set destroy information. */
+ rhc->rhc_mhook = bgp_route_match_delete;
+ rhc->rhc_rule = "src-peer";
+ rhc->rhc_event = RMAP_EVENT_MATCH_DELETED;
+
+ ret = bgp_route_match_add(rhc->rhc_rmi, "src-peer", peer, RMAP_EVENT_MATCH_ADDED,
+ args->errmsg, args->errmsg_len);
+
+ if (ret != RMAP_COMPILE_SUCCESS) {
+ rhc->rhc_mhook = NULL;
+ return NB_ERR_INCONSISTENCY;
+ }
+ }
+
+ return NB_OK;
+}
+
+int lib_route_map_entry_match_condition_rmap_match_condition_src_peer_ipv6_address_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ return lib_route_map_entry_match_destroy(args);
+ }
+
+ return NB_OK;
+}
+
+/*
* XPath: /frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:list-name
*/
int
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c
index 250378af68..1a66df59fc 100644
--- a/bgpd/bgp_updgrp_adv.c
+++ b/bgpd/bgp_updgrp_adv.c
@@ -906,8 +906,8 @@ void subgroup_default_originate(struct update_subgroup *subgrp, bool withdraw)
assert(attr.aspath);
aspath = attr.aspath;
- attr.med = 0;
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
+
+ bgp_attr_set_med(&attr, 0);
if ((afi == AFI_IP6) || peer_cap_enhe(peer, afi, safi)) {
/* IPv6 global nexthop must be included. */
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 1877d451ad..62b79541bf 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -4493,16 +4493,6 @@ DEFUN (bgp_network_import_check,
return CMD_SUCCESS;
}
-#if CONFDATE > 20241013
-CPP_NOTICE("Drop `bgp network import-check exact` command")
-#endif
-ALIAS_HIDDEN(bgp_network_import_check, bgp_network_import_check_exact_cmd,
- "bgp network import-check exact",
- BGP_STR
- "BGP network command\n"
- "Check BGP network route exists in IGP\n"
- "Match route precisely\n")
-
DEFUN (no_bgp_network_import_check,
no_bgp_network_import_check_cmd,
"no bgp network import-check",
@@ -20658,7 +20648,6 @@ void bgp_vty_init(void)
/* "bgp network import-check" commands. */
install_element(BGP_NODE, &bgp_network_import_check_cmd);
- install_element(BGP_NODE, &bgp_network_import_check_exact_cmd);
install_element(BGP_NODE, &no_bgp_network_import_check_cmd);
/* "bgp default local-preference" commands. */
diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c
index 23e3eb4823..61d154f1b4 100644
--- a/bgpd/rfapi/rfapi.c
+++ b/bgpd/rfapi/rfapi.c
@@ -667,10 +667,8 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF);
}
- if (med) {
- attr.med = *med;
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
- }
+ if (med)
+ bgp_attr_set_med(&attr, *med);
/* override default weight assigned by bgp_attr_default_set() */
attr.weight = rfd->peer ? rfd->peer->weight[afi][safi] : 0;
@@ -863,10 +861,8 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
red = bgp_redist_lookup(bgp, afi, type, 0);
- if (red && red->redist_metric_flag) {
- attr.med = red->redist_metric;
- attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
- }
+ if (red && red->redist_metric_flag)
+ bgp_attr_set_med(&attr, red->redist_metric);
bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
diff --git a/bgpd/rfapi/vnc_export_bgp.c b/bgpd/rfapi/vnc_export_bgp.c
index 4de2306609..c9a058ea44 100644
--- a/bgpd/rfapi/vnc_export_bgp.c
+++ b/bgpd/rfapi/vnc_export_bgp.c
@@ -96,15 +96,16 @@ static void encap_attr_export_ce(struct attr *new, struct attr *orig,
* neighbor NEIGHBOR attribute-unchanged med
*/
if (!CHECK_FLAG(new->flag, BGP_ATTR_MULTI_EXIT_DISC)) {
+ uint32_t med = 255;
+
if (CHECK_FLAG(new->flag, BGP_ATTR_LOCAL_PREF)) {
if (new->local_pref > 255)
- new->med = 0;
+ med = 0;
else
- new->med = 255 - new->local_pref;
- } else {
- new->med = 255; /* shouldn't happen */
+ med = 255 - new->local_pref;
}
- new->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
+
+ bgp_attr_set_med(new, med);
}
/*
@@ -642,15 +643,16 @@ encap_attr_export(struct attr *new, struct attr *orig,
* neighbor NEIGHBOR attribute-unchanged med
*/
if (!CHECK_FLAG(new->flag, BGP_ATTR_MULTI_EXIT_DISC)) {
+ uint32_t med = 255;
+
if (CHECK_FLAG(new->flag, BGP_ATTR_LOCAL_PREF)) {
if (new->local_pref > 255)
- new->med = 0;
+ med = 0;
else
- new->med = 255 - new->local_pref;
- } else {
- new->med = 255; /* shouldn't happen */
+ med = 255 - new->local_pref;
}
- new->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
+
+ bgp_attr_set_med(new, med);
}
/*
diff --git a/doc/user/routemap.rst b/doc/user/routemap.rst
index 9034af39c5..60e458a28a 100644
--- a/doc/user/routemap.rst
+++ b/doc/user/routemap.rst
@@ -190,6 +190,12 @@ Route Map Match Command
do the exact matching of the communities, while ``any`` - can match any
community specified in COMMUNITY_LIST.
+.. clicmd:: match src-peer [IPV4_ADDR|IPV6_ADDR|INTERFACE_NAME|PEER_GROUP_NAME]
+
+ This is a BGP specific match command. Matches the source peer if the neighbor
+ was specified in this manner. Useful to announce the routes that was originated
+ by the source peer.
+
.. clicmd:: match peer IPV4_ADDR
This is a BGP specific match command. Matches the peer ip address
@@ -305,13 +311,18 @@ Route Map Set Command
Set the route's weight.
-.. clicmd:: set metric <[+|-](1-4294967295)|rtt|+rtt|-rtt>
+.. clicmd:: set metric <[+|-](1-4294967295)|rtt|+rtt|-rtt|igp|aigp>
Set the route metric. When used with BGP, set the BGP attribute MED to a
specific value. Use `+`/`-` to add or subtract the specified value to/from
the existing/MED. Use `rtt` to set the MED to the round trip time or
`+rtt`/`-rtt` to add/subtract the round trip time to/from the MED.
+ If ``igp`` is specified, then the actual value from the IGP protocol is used.
+
+ If ``aigp`` is specified, then the actual value from the AIGP metric is used
+ (encoded as MED instead of AIGP attribute).
+
.. clicmd:: set min-metric <(0-4294967295)>
Set the minimum metric for the route.
diff --git a/isisd/isis_vty_fabricd.c b/isisd/isis_vty_fabricd.c
index 0d25f66109..85ef2c40a1 100644
--- a/isisd/isis_vty_fabricd.c
+++ b/isisd/isis_vty_fabricd.c
@@ -218,17 +218,9 @@ DEFUN (ip_router_isis,
if (!area)
isis_area_create(area_tag, VRF_DEFAULT_NAME);
- if (!circuit) {
+ if (!circuit)
circuit = isis_circuit_new(ifp, area_tag);
- if (circuit->state != C_STATE_CONF
- && circuit->state != C_STATE_UP) {
- vty_out(vty,
- "Couldn't bring up interface, please check log.\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- }
-
bool ip = circuit->ip_router, ipv6 = circuit->ipv6_router;
if (af[2] != '\0')
ipv6 = true;
diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c
index 6e844c0aa1..0a3a03bc38 100644
--- a/ldpd/ldpe.c
+++ b/ldpd/ldpe.c
@@ -459,6 +459,8 @@ static void ldpe_dispatch_main(struct event *thread)
tnbr_update_all(AF_UNSPEC);
break;
case IMSG_RECONF_CONF:
+ if (nconf)
+ ldp_clear_config(nconf);
if ((nconf = malloc(sizeof(struct ldpd_conf))) == NULL)
fatal(NULL);
memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
diff --git a/lib/command.h b/lib/command.h
index f369a35243..c60751789f 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -84,6 +84,7 @@ enum node_type {
CONFIG_NODE, /* Config node. Default mode of config file. */
PREFIX_NODE, /* ip prefix-list node. */
PREFIX_IPV6_NODE, /* ipv6 prefix-list node. */
+ RMAP_NODE, /* Route map node. */
LIB_DEBUG_NODE, /* frrlib debug node. */
DEBUG_NODE, /* Debug node. */
VRF_DEBUG_NODE, /* Vrf Debug node. */
@@ -136,7 +137,6 @@ enum node_type {
AS_LIST_NODE, /* AS list node. */
COMMUNITY_LIST_NODE, /* Community list node. */
COMMUNITY_ALIAS_NODE, /* Community alias node. */
- RMAP_NODE, /* Route map node. */
PBRMAP_NODE, /* PBR map node. */
SMUX_NODE, /* SNMP configuration node. */
DUMP_NODE, /* Packet dump node. */
diff --git a/lib/defun_lex.l b/lib/defun_lex.l
index 3104e48063..9528e44852 100644
--- a/lib/defun_lex.l
+++ b/lib/defun_lex.l
@@ -157,6 +157,9 @@ SPECIAL [(),]
%%
+#else
+extern int def_yylex(void);
+extern int def_yylex_destroy(void);
#endif /* __clang_analyzer__ */
static int yylex_clr(char **retbuf)
diff --git a/lib/netns_linux.c b/lib/netns_linux.c
index 8fa4bc6fe0..82162abfd4 100644
--- a/lib/netns_linux.c
+++ b/lib/netns_linux.c
@@ -258,7 +258,7 @@ static void ns_disable_internal(struct ns *ns)
if (ns_master.ns_disable_hook)
(*ns_master.ns_disable_hook)(ns);
- if (have_netns())
+ if (have_netns() && ns->fd >= 0)
close(ns->fd);
ns->fd = -1;
diff --git a/lib/ntop.c b/lib/ntop.c
index 89b4d5ecdc..edf03cd076 100644
--- a/lib/ntop.c
+++ b/lib/ntop.c
@@ -116,7 +116,18 @@ inet4:
best = i - curlen;
bestlen = curlen;
}
- /* do we want ::ffff:A.B.C.D? */
+ if (best == 0 && bestlen == 5 && b[10] == 0xff && b[11] == 0xff) {
+ /* ::ffff:A.B.C.D */
+ *o++ = ':';
+ *o++ = ':';
+ *o++ = 'f';
+ *o++ = 'f';
+ *o++ = 'f';
+ *o++ = 'f';
+ *o++ = ':';
+ b += 12;
+ goto inet4;
+ }
if (best == 0 && bestlen == 6) {
*o++ = ':';
*o++ = ':';
diff --git a/lib/ptm_lib.c b/lib/ptm_lib.c
index ac800be0a5..737c60775f 100644
--- a/lib/ptm_lib.c
+++ b/lib/ptm_lib.c
@@ -308,22 +308,18 @@ static int _ptm_lib_read_ptm_socket(int fd, char *buf, int len)
while (bytes_read != len) {
rc = recv(fd, (void *)(buf + bytes_read), (len - bytes_read),
MSG_DONTWAIT);
- if (rc <= 0) {
- if (errno && (errno != EAGAIN)
- && (errno != EWOULDBLOCK)) {
- ERRLOG("fatal recv error(%s), closing connection, rc %d\n",
- strerror(errno), rc);
- return (rc);
- } else {
- if (retries++ < 2) {
- usleep(10000);
- continue;
- }
- DLOG("max retries - recv error(%d - %s) bytes read %d (%d)\n",
- errno, strerror(errno), bytes_read, len);
- return (bytes_read);
+ if (rc < 0 && (errno != EAGAIN) && (errno != EWOULDBLOCK)) {
+ ERRLOG("fatal recv error(%s), closing connection, rc %d\n", strerror(errno),
+ rc);
+ return (rc);
+ } else if (rc <= 0) {
+ if (retries++ < 2) {
+ usleep(10000);
+ continue;
}
- break;
+ DLOG("max retries - recv error(%d - %s) bytes read %d (%d)\n", errno,
+ strerror(errno), bytes_read, len);
+ return (bytes_read);
} else {
bytes_read += rc;
}
diff --git a/lib/routemap.h b/lib/routemap.h
index dfb84ced5b..ef9b3cb160 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -278,6 +278,7 @@ DECLARE_QOBJ_TYPE(route_map);
#define IS_MATCH_SRC_VRF(C) \
(strmatch(C, "frr-bgp-route-map:source-vrf"))
#define IS_MATCH_PEER(C) (strmatch(C, "frr-bgp-route-map:peer"))
+#define IS_MATCH_SRC_PEER(C) (strmatch(C, "frr-bgp-route-map:src-peer"))
#define IS_MATCH_AS_LIST(C) \
(strmatch(C, "frr-bgp-route-map:as-path-list"))
#define IS_MATCH_MAC_LIST(C) \
diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c
index f64c3c2376..69b942064b 100644
--- a/lib/routemap_cli.c
+++ b/lib/routemap_cli.c
@@ -756,6 +756,18 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
acl = "local";
vty_out(vty, " match peer %s\n", acl);
+ } else if (IS_MATCH_SRC_PEER(condition)) {
+ acl = NULL;
+ ln = yang_dnode_get(dnode,
+ "./rmap-match-condition/frr-bgp-route-map:src-peer-ipv4-address");
+ if (!ln)
+ ln = yang_dnode_get(dnode,
+ "./rmap-match-condition/frr-bgp-route-map:src-peer-ipv6-address");
+ if (!ln)
+ ln = yang_dnode_get(dnode,
+ "./rmap-match-condition/frr-bgp-route-map:src-peer-interface");
+ acl = yang_dnode_get_string(ln, NULL);
+ vty_out(vty, " match src-peer %s\n", acl);
} else if (IS_MATCH_AS_LIST(condition)) {
vty_out(vty, " match as-path %s\n",
yang_dnode_get_string(
@@ -922,13 +934,15 @@ DEFPY_YANG(
DEFPY_YANG(
set_metric, set_metric_cmd,
- "set metric <(-4294967295-4294967295)$metric|rtt$rtt|+rtt$artt|-rtt$srtt>",
+ "set metric <(-4294967295-4294967295)$metric|rtt$rtt|+rtt$artt|-rtt$srtt|igp$igp|aigp$aigp>",
SET_STR
"Metric value for destination routing protocol\n"
"Metric value (use +/- for additions or subtractions)\n"
"Assign round trip time\n"
"Add round trip time\n"
- "Subtract round trip time\n")
+ "Subtract round trip time\n"
+ "Metric value from IGP protocol\n"
+ "Metric value from AIGP (Accumulated IGP)\n")
{
const char *xpath = "./set-action[action='frr-route-map:set-metric']";
char xpath_value[XPATH_MAXLEN];
@@ -939,6 +953,12 @@ DEFPY_YANG(
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-set-action/use-round-trip-time", xpath);
snprintf(value, sizeof(value), "true");
+ } else if (igp) {
+ snprintf(xpath_value, sizeof(xpath_value), "%s/rmap-set-action/use-igp", xpath);
+ snprintf(value, sizeof(value), "true");
+ } else if (aigp) {
+ snprintf(xpath_value, sizeof(xpath_value), "%s/rmap-set-action/use-aigp", xpath);
+ snprintf(value, sizeof(value), "true");
} else if (artt) {
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-set-action/add-round-trip-time", xpath);
@@ -1148,23 +1168,19 @@ void route_map_action_show(struct vty *vty, const struct lyd_node *dnode,
if (yang_dnode_get(dnode,
"./rmap-set-action/use-round-trip-time")) {
vty_out(vty, " set metric rtt\n");
- } else if (yang_dnode_get(
- dnode,
- "./rmap-set-action/add-round-trip-time")) {
+ } else if (yang_dnode_get(dnode, "./rmap-set-action/use-igp")) {
+ vty_out(vty, " set metric igp\n");
+ } else if (yang_dnode_get(dnode, "./rmap-set-action/use-aigp")) {
+ vty_out(vty, " set metric aigp\n");
+ } else if (yang_dnode_get(dnode, "./rmap-set-action/add-round-trip-time")) {
vty_out(vty, " set metric +rtt\n");
- } else if (
- yang_dnode_get(
- dnode,
- "./rmap-set-action/subtract-round-trip-time")) {
+ } else if (yang_dnode_get(dnode, "./rmap-set-action/subtract-round-trip-time")) {
vty_out(vty, " set metric -rtt\n");
- } else if (yang_dnode_get(dnode,
- "./rmap-set-action/add-metric")) {
+ } else if (yang_dnode_get(dnode, "./rmap-set-action/add-metric")) {
vty_out(vty, " set metric +%s\n",
yang_dnode_get_string(
dnode, "./rmap-set-action/add-metric"));
- } else if (yang_dnode_get(
- dnode,
- "./rmap-set-action/subtract-metric")) {
+ } else if (yang_dnode_get(dnode, "./rmap-set-action/subtract-metric")) {
vty_out(vty, " set metric -%s\n",
yang_dnode_get_string(
dnode,
diff --git a/lib/routemap_northbound.c b/lib/routemap_northbound.c
index 1bba4dad47..0ee055e653 100644
--- a/lib/routemap_northbound.c
+++ b/lib/routemap_northbound.c
@@ -1214,6 +1214,34 @@ static int lib_route_map_entry_set_action_use_round_trip_time_destroy(
}
/*
+ * XPath: /frr-route-map:lib/route-map/entry/set-action/use-igp
+ */
+static int lib_route_map_entry_set_action_use_igp_modify(struct nb_cb_modify_args *args)
+{
+ return set_action_modify(args->event, args->dnode, args->resource, "igp", args->errmsg,
+ args->errmsg_len);
+}
+
+static int lib_route_map_entry_set_action_use_igp_destroy(struct nb_cb_destroy_args *args)
+{
+ return lib_route_map_entry_set_action_value_destroy(args);
+}
+
+/*
+ * XPath: /frr-route-map:lib/route-map/entry/set-action/use-aigp
+ */
+static int lib_route_map_entry_set_action_use_aigp_modify(struct nb_cb_modify_args *args)
+{
+ return set_action_modify(args->event, args->dnode, args->resource, "aigp", args->errmsg,
+ args->errmsg_len);
+}
+
+static int lib_route_map_entry_set_action_use_aigp_destroy(struct nb_cb_destroy_args *args)
+{
+ return lib_route_map_entry_set_action_value_destroy(args);
+}
+
+/*
* XPath: /frr-route-map:lib/route-map/entry/set-action/add-round-trip-time
*/
static int lib_route_map_entry_set_action_add_round_trip_time_modify(
@@ -1517,6 +1545,20 @@ const struct frr_yang_module_info frr_route_map_info = {
}
},
{
+ .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/use-igp",
+ .cbs = {
+ .modify = lib_route_map_entry_set_action_use_igp_modify,
+ .destroy = lib_route_map_entry_set_action_use_igp_destroy,
+ }
+ },
+ {
+ .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/use-aigp",
+ .cbs = {
+ .modify = lib_route_map_entry_set_action_use_aigp_modify,
+ .destroy = lib_route_map_entry_set_action_use_aigp_destroy,
+ }
+ },
+ {
.xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/add-round-trip-time",
.cbs = {
.modify = lib_route_map_entry_set_action_add_round_trip_time_modify,
diff --git a/lib/zclient.c b/lib/zclient.c
index 0e832f0d8f..557d9c3eb9 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -2374,7 +2374,7 @@ static bool zapi_nexthop_update_decode(struct stream *s, struct prefix *match,
STREAM_GETW(s, nhr->instance);
STREAM_GETC(s, nhr->distance);
STREAM_GETL(s, nhr->metric);
- STREAM_GETC(s, nhr->nexthop_num);
+ STREAM_GETW(s, nhr->nexthop_num);
for (i = 0; i < nhr->nexthop_num; i++) {
if (zapi_nexthop_decode(s, &(nhr->nexthops[i]), 0, 0) != 0)
diff --git a/lib/zclient.h b/lib/zclient.h
index 91c0c9ed6d..6da9558aa5 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -251,21 +251,16 @@ enum zebra_error_types {
static inline const char *zebra_error_type2str(enum zebra_error_types type)
{
- const char *ret = "UNKNOWN";
-
switch (type) {
case ZEBRA_UNKNOWN_ERROR:
- ret = "ZEBRA_UNKNOWN_ERROR";
- break;
+ return "ZEBRA_UNKNOWN_ERROR";
case ZEBRA_NO_VRF:
- ret = "ZEBRA_NO_VRF";
- break;
+ return "ZEBRA_NO_VRF";
case ZEBRA_INVALID_MSG_TYPE:
- ret = "ZEBRA_INVALID_MSG_TYPE";
- break;
+ return "ZEBRA_INVALID_MSG_TYPE";
}
- return ret;
+ return "UNKNOWN";
}
struct redist_proto {
@@ -780,69 +775,51 @@ enum zclient_send_status {
static inline const char *
zapi_nhg_notify_owner2str(enum zapi_nhg_notify_owner note)
{
- const char *ret = "UNKNOWN";
-
switch (note) {
case ZAPI_NHG_FAIL_INSTALL:
- ret = "ZAPI_NHG_FAIL_INSTALL";
- break;
+ return "ZAPI_NHG_FAIL_INSTALL";
case ZAPI_NHG_INSTALLED:
- ret = "ZAPI_NHG_INSTALLED";
- break;
+ return "ZAPI_NHG_INSTALLED";
case ZAPI_NHG_REMOVE_FAIL:
- ret = "ZAPI_NHG_REMOVE_FAIL";
- break;
+ return "ZAPI_NHG_REMOVE_FAIL";
case ZAPI_NHG_REMOVED:
- ret = "ZAPI_NHG_REMOVED";
- break;
+ return "ZAPI_NHG_REMOVED";
}
- return ret;
+ return "UNKNOWN";
}
static inline const char *
zapi_rule_notify_owner2str(enum zapi_rule_notify_owner note)
{
- const char *ret = "UNKNOWN";
-
switch (note) {
case ZAPI_RULE_FAIL_INSTALL:
- ret = "ZAPI_RULE_FAIL_INSTALL";
- break;
+ return "ZAPI_RULE_FAIL_INSTALL";
case ZAPI_RULE_INSTALLED:
- ret = "ZAPI_RULE_INSTALLED";
- break;
+ return "ZAPI_RULE_INSTALLED";
case ZAPI_RULE_FAIL_REMOVE:
- ret = "ZAPI_RULE_FAIL_REMOVE";
- break;
+ return "ZAPI_RULE_FAIL_REMOVE";
case ZAPI_RULE_REMOVED:
- ret = "ZAPI_RULE_REMOVED";
- break;
+ return "ZAPI_RULE_REMOVED";
}
- return ret;
+ return "UNKNOWN";
}
static inline const char *zapi_srv6_sid_notify2str(enum zapi_srv6_sid_notify note)
{
- const char *ret = "UNKNOWN";
-
switch (note) {
case ZAPI_SRV6_SID_FAIL_ALLOC:
- ret = "ZAPI_SRV6_SID_FAIL_ALLOC";
- break;
+ return "ZAPI_SRV6_SID_FAIL_ALLOC";
case ZAPI_SRV6_SID_ALLOCATED:
- ret = "ZAPI_SRV6_SID_ALLOCATED";
- break;
+ return "ZAPI_SRV6_SID_ALLOCATED";
case ZAPI_SRV6_SID_FAIL_RELEASE:
- ret = "ZAPI_SRV6_SID_FAIL_RELEASE";
- break;
+ return "ZAPI_SRV6_SID_FAIL_RELEASE";
case ZAPI_SRV6_SID_RELEASED:
- ret = "ZAPI_SRV6_SID_RELEASED";
- break;
+ return "ZAPI_SRV6_SID_RELEASED";
}
- return ret;
+ return "UNKNOWN";
}
/* Zebra MAC types */
diff --git a/lib/zlog_5424_cli.c b/lib/zlog_5424_cli.c
index 3003df542f..f97c426463 100644
--- a/lib/zlog_5424_cli.c
+++ b/lib/zlog_5424_cli.c
@@ -674,6 +674,7 @@ static int log_5424_config_write(struct vty *vty)
vty_out(vty, "log extended %s\n", cfg->name);
+ (void)fmt_str; /* clang-SA */
switch (cfg->cfg.fmt) {
case ZLOG_FMT_5424:
fmt_str = " format rfc5424";
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index f125fa93b1..a8b8de6d5b 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -2613,8 +2613,7 @@ void ospf_external_lsa_refresh_default(struct ospf *ospf)
}
}
-void ospf_external_lsa_refresh_type(struct ospf *ospf, uint8_t type,
- unsigned short instance, int force)
+void ospf_external_lsa_refresh_type(struct ospf *ospf, uint8_t type, uint8_t instance, int force)
{
struct route_node *rn;
struct external_info *ei;
@@ -3170,9 +3169,9 @@ int ospf_check_nbr_status(struct ospf *ospf)
}
-void ospf_maxage_lsa_remover(struct event *thread)
+void ospf_maxage_lsa_remover(struct event *event)
{
- struct ospf *ospf = EVENT_ARG(thread);
+ struct ospf *ospf = EVENT_ARG(event);
struct ospf_lsa *lsa, *old;
struct route_node *rn;
int reschedule = 0;
@@ -3202,7 +3201,7 @@ void ospf_maxage_lsa_remover(struct event *thread)
}
/* TODO: maybe convert this function to a work-queue */
- if (event_should_yield(thread)) {
+ if (event_should_yield(event)) {
OSPF_TIMER_ON(ospf->t_maxage,
ospf_maxage_lsa_remover, 0);
route_unlock_node(
@@ -3418,9 +3417,9 @@ static int ospf_lsa_maxage_walker_remover(struct ospf *ospf,
}
/* Periodical check of MaxAge LSA. */
-void ospf_lsa_maxage_walker(struct event *thread)
+void ospf_lsa_maxage_walker(struct event *event)
{
- struct ospf *ospf = EVENT_ARG(thread);
+ struct ospf *ospf = EVENT_ARG(event);
struct route_node *rn;
struct ospf_lsa *lsa;
struct ospf_area *area;
@@ -4157,11 +4156,11 @@ void ospf_refresher_unregister_lsa(struct ospf *ospf, struct ospf_lsa *lsa)
}
}
-void ospf_lsa_refresh_walker(struct event *t)
+void ospf_lsa_refresh_walker(struct event *e)
{
struct list *refresh_list;
struct listnode *node, *nnode;
- struct ospf *ospf = EVENT_ARG(t);
+ struct ospf *ospf = EVENT_ARG(e);
struct ospf_lsa *lsa;
int i;
struct list *lsa_to_refresh = list_new();
diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h
index d5ca0694cc..c751f081fb 100644
--- a/ospfd/ospf_lsa.h
+++ b/ospfd/ospf_lsa.h
@@ -225,122 +225,111 @@ enum lsid_status { LSID_AVAILABLE = 0, LSID_CHANGE, LSID_NOT_AVAILABLE };
/* Prototypes. */
/* XXX: Eek, time functions, similar are in lib/thread.c */
extern struct timeval int2tv(int);
-extern struct timeval msec2tv(int);
+extern struct timeval msec2tv(int a);
-extern int get_age(struct ospf_lsa *);
-extern uint16_t ospf_lsa_checksum(struct lsa_header *);
-extern int ospf_lsa_checksum_valid(struct lsa_header *);
-extern int ospf_lsa_refresh_delay(struct ospf_lsa *);
+extern int get_age(struct ospf_lsa *lsa);
+extern uint16_t ospf_lsa_checksum(struct lsa_header *lsah);
+extern int ospf_lsa_checksum_valid(struct lsa_header *lsah);
+extern int ospf_lsa_refresh_delay(struct ospf_lsa *lsa);
-extern const char *dump_lsa_key(struct ospf_lsa *);
-extern uint32_t lsa_seqnum_increment(struct ospf_lsa *);
-extern void lsa_header_set(struct stream *, uint8_t, uint8_t, struct in_addr,
- struct in_addr);
-extern struct ospf_neighbor *ospf_nbr_lookup_ptop(struct ospf_interface *);
-extern int ospf_check_nbr_status(struct ospf *);
+extern const char *dump_lsa_key(struct ospf_lsa *lsa);
+extern uint32_t lsa_seqnum_increment(struct ospf_lsa *lsa);
+extern void lsa_header_set(struct stream *s, uint8_t options, uint8_t type, struct in_addr id,
+ struct in_addr router_id);
+extern struct ospf_neighbor *ospf_nbr_lookup_ptop(struct ospf_interface *oi);
+extern int ospf_check_nbr_status(struct ospf *ospf);
/* Prototype for LSA primitive. */
extern struct ospf_lsa *ospf_lsa_new(void);
extern struct ospf_lsa *ospf_lsa_new_and_data(size_t size);
-extern struct ospf_lsa *ospf_lsa_dup(struct ospf_lsa *);
-extern void ospf_lsa_free(struct ospf_lsa *);
-extern struct ospf_lsa *ospf_lsa_lock(struct ospf_lsa *);
-extern void ospf_lsa_unlock(struct ospf_lsa **);
-extern void ospf_lsa_discard(struct ospf_lsa *);
-extern int ospf_lsa_flush_schedule(struct ospf *, struct ospf_lsa *);
-extern struct lsa_header *ospf_lsa_data_new(size_t);
-extern struct lsa_header *ospf_lsa_data_dup(struct lsa_header *);
-extern void ospf_lsa_data_free(struct lsa_header *);
+extern struct ospf_lsa *ospf_lsa_dup(struct ospf_lsa *lsa);
+extern void ospf_lsa_free(struct ospf_lsa *lsa);
+extern struct ospf_lsa *ospf_lsa_lock(struct ospf_lsa *lsa);
+extern void ospf_lsa_unlock(struct ospf_lsa **lsa);
+extern void ospf_lsa_discard(struct ospf_lsa *lsa);
+extern int ospf_lsa_flush_schedule(struct ospf *ospf, struct ospf_lsa *lsa);
+extern struct lsa_header *ospf_lsa_data_new(size_t size);
+extern struct lsa_header *ospf_lsa_data_dup(struct lsa_header *lsah);
+extern void ospf_lsa_data_free(struct lsa_header *lsah);
/* Prototype for various LSAs */
extern void ospf_router_lsa_body_set(struct stream **s, struct ospf_area *area);
extern uint8_t router_lsa_flags(struct ospf_area *area);
-extern int ospf_router_lsa_update(struct ospf *);
-extern int ospf_router_lsa_update_area(struct ospf_area *);
+extern int ospf_router_lsa_update(struct ospf *ospf);
+extern int ospf_router_lsa_update_area(struct ospf_area *area);
-extern void ospf_network_lsa_update(struct ospf_interface *);
+extern void ospf_network_lsa_update(struct ospf_interface *oi);
-extern struct ospf_lsa *
-ospf_summary_lsa_originate(struct prefix_ipv4 *, uint32_t, struct ospf_area *);
-extern struct ospf_lsa *ospf_summary_asbr_lsa_originate(struct prefix_ipv4 *,
- uint32_t,
- struct ospf_area *);
+extern struct ospf_lsa *ospf_summary_lsa_originate(struct prefix_ipv4 *p, uint32_t metric,
+ struct ospf_area *area);
+extern struct ospf_lsa *ospf_summary_asbr_lsa_originate(struct prefix_ipv4 *p, uint32_t metric,
+ struct ospf_area *area);
-extern struct ospf_lsa *ospf_lsa_install(struct ospf *, struct ospf_interface *,
- struct ospf_lsa *);
+extern struct ospf_lsa *ospf_lsa_install(struct ospf *ospf, struct ospf_interface *oi,
+ struct ospf_lsa *lsa);
extern void ospf_nssa_lsa_flush(struct ospf *ospf, struct prefix_ipv4 *p);
-extern void ospf_external_lsa_flush(struct ospf *, uint8_t,
- struct prefix_ipv4 *,
+extern void ospf_external_lsa_flush(struct ospf *ospf, uint8_t type, struct prefix_ipv4 *p,
ifindex_t /* , struct in_addr nexthop */);
-extern struct in_addr ospf_get_ip_from_ifp(struct ospf_interface *);
+extern struct in_addr ospf_get_ip_from_ifp(struct ospf_interface *oi);
-extern struct ospf_lsa *ospf_external_lsa_originate(struct ospf *,
- struct external_info *);
+extern struct ospf_lsa *ospf_external_lsa_originate(struct ospf *ospf, struct external_info *ei);
extern struct ospf_lsa *ospf_nssa_lsa_originate(struct ospf_area *area,
struct external_info *ei);
extern struct ospf_lsa *ospf_nssa_lsa_refresh(struct ospf_area *area,
struct ospf_lsa *lsa,
struct external_info *ei);
extern void ospf_external_lsa_rid_change(struct ospf *ospf);
-extern struct ospf_lsa *ospf_lsa_lookup(struct ospf *ospf, struct ospf_area *,
- uint32_t, struct in_addr,
- struct in_addr);
-extern struct ospf_lsa *ospf_lsa_lookup_by_id(struct ospf_area *, uint32_t,
- struct in_addr);
-extern struct ospf_lsa *ospf_lsa_lookup_by_header(struct ospf_area *,
- struct lsa_header *);
-extern int ospf_lsa_more_recent(struct ospf_lsa *, struct ospf_lsa *);
-extern int ospf_lsa_different(struct ospf_lsa *, struct ospf_lsa *,
- bool ignore_rcvd_flag);
-extern void ospf_flush_self_originated_lsas_now(struct ospf *);
-
-extern int ospf_lsa_is_self_originated(struct ospf *, struct ospf_lsa *);
-
-extern struct ospf_lsa *ospf_lsa_lookup_by_prefix(struct ospf_lsdb *, uint8_t,
- struct prefix_ipv4 *,
- struct in_addr);
-
-extern void ospf_lsa_maxage(struct ospf *, struct ospf_lsa *);
-extern uint32_t get_metric(uint8_t *);
-
-extern void ospf_lsa_maxage_walker(struct event *thread);
-extern struct ospf_lsa *ospf_lsa_refresh(struct ospf *, struct ospf_lsa *);
-
-extern void ospf_external_lsa_refresh_default(struct ospf *);
-
-extern void ospf_external_lsa_refresh_type(struct ospf *, uint8_t,
- unsigned short, int);
-extern struct ospf_lsa *ospf_external_lsa_refresh(struct ospf *,
- struct ospf_lsa *,
- struct external_info *, int,
- bool aggr);
+extern struct ospf_lsa *ospf_lsa_lookup(struct ospf *ospf, struct ospf_area *area, uint32_t type,
+ struct in_addr id, struct in_addr adv_router);
+extern struct ospf_lsa *ospf_lsa_lookup_by_id(struct ospf_area *area, uint32_t type,
+ struct in_addr id);
+extern struct ospf_lsa *ospf_lsa_lookup_by_header(struct ospf_area *area, struct lsa_header *lsah);
+extern int ospf_lsa_more_recent(struct ospf_lsa *l1, struct ospf_lsa *l2);
+extern int ospf_lsa_different(struct ospf_lsa *l1, struct ospf_lsa *l2, bool ignore_rcvd_flag);
+extern void ospf_flush_self_originated_lsas_now(struct ospf *ospf);
+
+extern int ospf_lsa_is_self_originated(struct ospf *ospf, struct ospf_lsa *lsa);
+
+extern struct ospf_lsa *ospf_lsa_lookup_by_prefix(struct ospf_lsdb *lsdb, uint8_t type,
+ struct prefix_ipv4 *p, struct in_addr router_id);
+
+extern void ospf_lsa_maxage(struct ospf *ospf, struct ospf_lsa *lsa);
+extern uint32_t get_metric(uint8_t *metric);
+
+extern void ospf_lsa_maxage_walker(struct event *event);
+extern struct ospf_lsa *ospf_lsa_refresh(struct ospf *ospf, struct ospf_lsa *lsa);
+
+extern void ospf_external_lsa_refresh_default(struct ospf *ospf);
+
+extern void ospf_external_lsa_refresh_type(struct ospf *ospf, uint8_t type, uint8_t instance,
+ int force);
+extern struct ospf_lsa *ospf_external_lsa_refresh(struct ospf *ospf, struct ospf_lsa *lsa,
+ struct external_info *ei, int force, bool aggr);
extern enum lsid_status ospf_lsa_unique_id(struct ospf *ospf,
struct ospf_lsdb *lsdb,
uint8_t type, struct prefix_ipv4 *p,
struct in_addr *addr);
-extern void ospf_schedule_lsa_flood_area(struct ospf_area *, struct ospf_lsa *);
-extern void ospf_schedule_lsa_flush_area(struct ospf_area *, struct ospf_lsa *);
+extern void ospf_schedule_lsa_flood_area(struct ospf_area *area, struct ospf_lsa *lsa);
+extern void ospf_schedule_lsa_flush_area(struct ospf_area *area, struct ospf_lsa *lsa);
-extern void ospf_refresher_register_lsa(struct ospf *, struct ospf_lsa *);
-extern void ospf_refresher_unregister_lsa(struct ospf *, struct ospf_lsa *);
-extern void ospf_lsa_refresh_walker(struct event *thread);
+extern void ospf_refresher_register_lsa(struct ospf *ospf, struct ospf_lsa *lsa);
+extern void ospf_refresher_unregister_lsa(struct ospf *ospf, struct ospf_lsa *lsa);
+extern void ospf_lsa_refresh_walker(struct event *event);
-extern void ospf_lsa_maxage_delete(struct ospf *, struct ospf_lsa *);
+extern void ospf_lsa_maxage_delete(struct ospf *ospf, struct ospf_lsa *lsa);
-extern void ospf_discard_from_db(struct ospf *, struct ospf_lsdb *,
- struct ospf_lsa *);
+extern void ospf_discard_from_db(struct ospf *ospf, struct ospf_lsdb *lsdb, struct ospf_lsa *lsa);
-extern int metric_type(struct ospf *, uint8_t, unsigned short);
-extern int metric_value(struct ospf *, uint8_t, unsigned short);
+extern int metric_type(struct ospf *ospf, uint8_t src, unsigned short instance);
+extern int metric_value(struct ospf *ospf, uint8_t src, unsigned short instance);
extern char link_info_set(struct stream **s, struct in_addr id,
struct in_addr data, uint8_t type, uint8_t tos,
uint16_t cost);
-extern struct in_addr ospf_get_nssa_ip(struct ospf_area *);
-extern int ospf_translated_nssa_compare(struct ospf_lsa *, struct ospf_lsa *);
+extern struct in_addr ospf_get_nssa_ip(struct ospf_area *area);
extern struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf,
struct ospf_lsa *type7,
struct ospf_lsa *type5);
@@ -351,7 +340,7 @@ extern void ospf_check_and_gen_init_seq_lsa(struct ospf_interface *oi,
struct ospf_lsa *lsa);
extern void ospf_flush_lsa_from_area(struct ospf *ospf, struct in_addr area_id,
int type);
-extern void ospf_maxage_lsa_remover(struct event *thread);
+extern void ospf_maxage_lsa_remover(struct event *event);
extern bool ospf_check_dna_lsa(const struct ospf_lsa *lsa);
extern void ospf_refresh_area_self_lsas(struct ospf_area *area);
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index b7261da261..01cbfedc1c 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -718,7 +718,7 @@ DEFUN (ospf_area_range_not_advertise,
DEFUN (no_ospf_area_range,
no_ospf_area_range_cmd,
- "no area <A.B.C.D|(0-4294967295)> range A.B.C.D/M [<cost (0-16777215)|advertise [cost (0-16777215)]|not-advertise>]",
+ "no area <A.B.C.D|(0-4294967295)> range A.B.C.D/M [<cost [(0-16777215)]|advertise [cost [(0-16777215)]]|not-advertise>]",
NO_STR
"OSPF area parameters\n"
"OSPF area ID in IP address format\n"
@@ -781,6 +781,8 @@ DEFUN (no_ospf_area_range_substitute,
ospf_area_range_substitute_unset(ospf, area, &p);
+ ospf_area_check_free(ospf, area_id);
+
return CMD_SUCCESS;
}
@@ -1353,12 +1355,13 @@ DEFUN (ospf_area_shortcut,
DEFUN (no_ospf_area_shortcut,
no_ospf_area_shortcut_cmd,
- "no area <A.B.C.D|(0-4294967295)> shortcut <enable|disable>",
+ "no area <A.B.C.D|(0-4294967295)> shortcut <default|enable|disable>",
NO_STR
"OSPF area parameters\n"
"OSPF area ID in IP address format\n"
"OSPF area ID as a decimal value\n"
"Deconfigure the area's shortcutting mode\n"
+ "Deconfigure default shortcutting through the area\n"
"Deconfigure enabled shortcutting through the area\n"
"Deconfigure disabled shortcutting through the area\n")
{
diff --git a/pimd/pim6_mld.c b/pimd/pim6_mld.c
index a871837701..59cd9aea5f 100644
--- a/pimd/pim6_mld.c
+++ b/pimd/pim6_mld.c
@@ -468,6 +468,8 @@ static void gm_sg_update(struct gm_sg *sg, bool has_expired)
static void gm_packet_free(struct gm_packet_state *pkt)
{
+ assert(pkt->iface);
+
gm_packet_expires_del(pkt->iface->expires, pkt);
gm_packets_del(pkt->subscriber->packets, pkt);
gm_subscriber_drop(&pkt->subscriber);
diff --git a/pimd/pim_autorp.c b/pimd/pim_autorp.c
index 35347a2790..3fc30347a6 100644
--- a/pimd/pim_autorp.c
+++ b/pimd/pim_autorp.c
@@ -308,7 +308,7 @@ static bool pim_autorp_discovery(struct pim_autorp *autorp, uint8_t rpcnt,
struct autorp_pkt_grp *grp;
size_t offset = 0;
pim_addr rp_addr;
- struct prefix grppfix;
+ struct prefix grppfix = {};
char plname[32];
struct prefix_list *pl;
struct prefix_list_entry *ple;
diff --git a/pimd/pim_bsr_rpdb.c b/pimd/pim_bsr_rpdb.c
index 3ec9f99cd1..6e93b65f4b 100644
--- a/pimd/pim_bsr_rpdb.c
+++ b/pimd/pim_bsr_rpdb.c
@@ -502,6 +502,9 @@ int pim_crp_process(struct interface *ifp, pim_sgaddr *src_dst, uint8_t *buf,
buf += sizeof(*crp_hdr);
remain -= sizeof(*crp_hdr);
+ /* ignore trailing data */
+ (void)buf;
+
size_t ngroups = crp_hdr->prefix_cnt;
if (remain < ngroups * sizeof(struct pim_encoded_group_ipv4)) {
diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c
index c19119fa47..5d344f1f66 100644
--- a/pimd/pim_zlookup.c
+++ b/pimd/pim_zlookup.c
@@ -193,7 +193,7 @@ static int zclient_read_nexthop(struct pim_instance *pim,
distance = stream_getc(s);
metric = stream_getl(s);
- nexthop_num = stream_getc(s);
+ nexthop_num = stream_getw(s);
if (nexthop_num < 1 || nexthop_num > router->multipath) {
if (PIM_DEBUG_PIM_NHT_DETAIL)
diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c
index 420ed7903b..d76befc131 100644
--- a/staticd/static_zebra.c
+++ b/staticd/static_zebra.c
@@ -43,7 +43,7 @@ struct static_nht_data {
vrf_id_t nh_vrf_id;
uint32_t refcount;
- uint8_t nh_num;
+ uint16_t nh_num;
bool registered;
};
diff --git a/tests/isisd/test_fuzz_isis_tlv_tests.h.gz b/tests/isisd/test_fuzz_isis_tlv_tests.h.gz
index 05e9f723a1..902b671b32 100644
--- a/tests/isisd/test_fuzz_isis_tlv_tests.h.gz
+++ b/tests/isisd/test_fuzz_isis_tlv_tests.h.gz
Binary files differ
diff --git a/tests/topotests/bfd_isis_topo1/rt1/step1/show_ipv6_route.ref b/tests/topotests/bfd_isis_topo1/rt1/step1/show_ipv6_route.ref
index 68d3fe2c44..a760f1c249 100644
--- a/tests/topotests/bfd_isis_topo1/rt1/step1/show_ipv6_route.ref
+++ b/tests/topotests/bfd_isis_topo1/rt1/step1/show_ipv6_route.ref
@@ -1,7 +1,7 @@
{
- "::ffff:202:202\/128":[
+ "::ffff:2.2.2.2\/128":[
{
- "prefix":"::ffff:202:202\/128",
+ "prefix":"::ffff:2.2.2.2\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
@@ -16,9 +16,9 @@
]
}
],
- "::ffff:303:303\/128":[
+ "::ffff:3.3.3.3\/128":[
{
- "prefix":"::ffff:303:303\/128",
+ "prefix":"::ffff:3.3.3.3\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
@@ -33,9 +33,9 @@
]
}
],
- "::ffff:404:404\/128":[
+ "::ffff:4.4.4.4\/128":[
{
- "prefix":"::ffff:404:404\/128",
+ "prefix":"::ffff:4.4.4.4\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
@@ -50,9 +50,9 @@
]
}
],
- "::ffff:505:505\/128":[
+ "::ffff:5.5.5.5\/128":[
{
- "prefix":"::ffff:505:505\/128",
+ "prefix":"::ffff:5.5.5.5\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
diff --git a/tests/topotests/bfd_isis_topo1/rt1/step3/show_ipv6_route_healthy.ref b/tests/topotests/bfd_isis_topo1/rt1/step3/show_ipv6_route_healthy.ref
index 68d3fe2c44..a760f1c249 100644
--- a/tests/topotests/bfd_isis_topo1/rt1/step3/show_ipv6_route_healthy.ref
+++ b/tests/topotests/bfd_isis_topo1/rt1/step3/show_ipv6_route_healthy.ref
@@ -1,7 +1,7 @@
{
- "::ffff:202:202\/128":[
+ "::ffff:2.2.2.2\/128":[
{
- "prefix":"::ffff:202:202\/128",
+ "prefix":"::ffff:2.2.2.2\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
@@ -16,9 +16,9 @@
]
}
],
- "::ffff:303:303\/128":[
+ "::ffff:3.3.3.3\/128":[
{
- "prefix":"::ffff:303:303\/128",
+ "prefix":"::ffff:3.3.3.3\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
@@ -33,9 +33,9 @@
]
}
],
- "::ffff:404:404\/128":[
+ "::ffff:4.4.4.4\/128":[
{
- "prefix":"::ffff:404:404\/128",
+ "prefix":"::ffff:4.4.4.4\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
@@ -50,9 +50,9 @@
]
}
],
- "::ffff:505:505\/128":[
+ "::ffff:5.5.5.5\/128":[
{
- "prefix":"::ffff:505:505\/128",
+ "prefix":"::ffff:5.5.5.5\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
diff --git a/tests/topotests/bfd_isis_topo1/rt1/step3/show_ipv6_route_rt2_down.ref b/tests/topotests/bfd_isis_topo1/rt1/step3/show_ipv6_route_rt2_down.ref
index 200053c3e8..1168765457 100644
--- a/tests/topotests/bfd_isis_topo1/rt1/step3/show_ipv6_route_rt2_down.ref
+++ b/tests/topotests/bfd_isis_topo1/rt1/step3/show_ipv6_route_rt2_down.ref
@@ -1,7 +1,7 @@
{
- "::ffff:202:202\/128":[
+ "::ffff:2.2.2.2\/128":[
{
- "prefix":"::ffff:202:202\/128",
+ "prefix":"::ffff:2.2.2.2\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
@@ -16,9 +16,9 @@
]
}
],
- "::ffff:303:303\/128":[
+ "::ffff:3.3.3.3\/128":[
{
- "prefix":"::ffff:303:303\/128",
+ "prefix":"::ffff:3.3.3.3\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
@@ -33,9 +33,9 @@
]
}
],
- "::ffff:404:404\/128":[
+ "::ffff:4.4.4.4\/128":[
{
- "prefix":"::ffff:404:404\/128",
+ "prefix":"::ffff:4.4.4.4\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
@@ -50,9 +50,9 @@
]
}
],
- "::ffff:505:505\/128":[
+ "::ffff:5.5.5.5\/128":[
{
- "prefix":"::ffff:505:505\/128",
+ "prefix":"::ffff:5.5.5.5\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
diff --git a/tests/topotests/bfd_isis_topo1/rt1/step3/show_ipv6_route_rt3_down.ref b/tests/topotests/bfd_isis_topo1/rt1/step3/show_ipv6_route_rt3_down.ref
index 4297f163b5..3e8505e79b 100644
--- a/tests/topotests/bfd_isis_topo1/rt1/step3/show_ipv6_route_rt3_down.ref
+++ b/tests/topotests/bfd_isis_topo1/rt1/step3/show_ipv6_route_rt3_down.ref
@@ -1,7 +1,7 @@
{
- "::ffff:202:202\/128":[
+ "::ffff:2.2.2.2\/128":[
{
- "prefix":"::ffff:202:202\/128",
+ "prefix":"::ffff:2.2.2.2\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
@@ -16,9 +16,9 @@
]
}
],
- "::ffff:303:303\/128":[
+ "::ffff:3.3.3.3\/128":[
{
- "prefix":"::ffff:303:303\/128",
+ "prefix":"::ffff:3.3.3.3\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
@@ -33,9 +33,9 @@
]
}
],
- "::ffff:404:404\/128":[
+ "::ffff:4.4.4.4\/128":[
{
- "prefix":"::ffff:404:404\/128",
+ "prefix":"::ffff:4.4.4.4\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
@@ -50,9 +50,9 @@
]
}
],
- "::ffff:505:505\/128":[
+ "::ffff:5.5.5.5\/128":[
{
- "prefix":"::ffff:505:505\/128",
+ "prefix":"::ffff:5.5.5.5\/128",
"protocol":"isis",
"selected":true,
"destSelected":true,
diff --git a/tests/topotests/bfd_isis_topo1/rt1/zebra.conf b/tests/topotests/bfd_isis_topo1/rt1/zebra.conf
index 7e6f7881b4..bf2428e625 100644
--- a/tests/topotests/bfd_isis_topo1/rt1/zebra.conf
+++ b/tests/topotests/bfd_isis_topo1/rt1/zebra.conf
@@ -10,7 +10,7 @@ hostname rt1
!
interface lo
ip address 1.1.1.1/32
- ipv6 address ::ffff:0101:0101/128
+ ipv6 address ::ffff:1.1.1.1/128
!
interface eth-rt2
ip address 10.0.1.1/24
diff --git a/tests/topotests/bfd_isis_topo1/rt2/zebra.conf b/tests/topotests/bfd_isis_topo1/rt2/zebra.conf
index 5788e31f12..1670c20506 100644
--- a/tests/topotests/bfd_isis_topo1/rt2/zebra.conf
+++ b/tests/topotests/bfd_isis_topo1/rt2/zebra.conf
@@ -7,7 +7,7 @@ hostname rt2
!
interface lo
ip address 2.2.2.2/32
- ipv6 address ::ffff:0202:0202/128
+ ipv6 address ::ffff:2.2.2.2/128
!
interface eth-rt1
ip address 10.0.1.2/24
diff --git a/tests/topotests/bfd_isis_topo1/rt3/zebra.conf b/tests/topotests/bfd_isis_topo1/rt3/zebra.conf
index 78eac2e15a..d59085560f 100644
--- a/tests/topotests/bfd_isis_topo1/rt3/zebra.conf
+++ b/tests/topotests/bfd_isis_topo1/rt3/zebra.conf
@@ -7,7 +7,7 @@ hostname rt3
!
interface lo
ip address 3.3.3.3/32
- ipv6 address ::ffff:0303:0303/128
+ ipv6 address ::ffff:3.3.3.3/128
!
interface eth-rt1
ip address 10.0.2.2/24
diff --git a/tests/topotests/bfd_isis_topo1/rt4/zebra.conf b/tests/topotests/bfd_isis_topo1/rt4/zebra.conf
index a6cb573ed8..66121662dd 100644
--- a/tests/topotests/bfd_isis_topo1/rt4/zebra.conf
+++ b/tests/topotests/bfd_isis_topo1/rt4/zebra.conf
@@ -7,7 +7,7 @@ hostname rt4
!
interface lo
ip address 4.4.4.4/32
- ipv6 address ::ffff:0404:0404/128
+ ipv6 address ::ffff:4.4.4.4/128
!
interface eth-rt3
ip address 10.0.4.2/24
diff --git a/tests/topotests/bfd_isis_topo1/rt5/zebra.conf b/tests/topotests/bfd_isis_topo1/rt5/zebra.conf
index 33473c91a3..d3331b5b6c 100644
--- a/tests/topotests/bfd_isis_topo1/rt5/zebra.conf
+++ b/tests/topotests/bfd_isis_topo1/rt5/zebra.conf
@@ -7,7 +7,7 @@ hostname rt5
!
interface lo
ip address 5.5.5.5/32
- ipv6 address ::ffff:0505:0505/128
+ ipv6 address ::ffff:5.5.5.5/128
!
interface eth-rt2
ip address 10.0.3.2/24
diff --git a/tests/topotests/bfd_ospf_topo1/rt1/step1/show_ipv6_route.ref b/tests/topotests/bfd_ospf_topo1/rt1/step1/show_ipv6_route.ref
index 6465efb8b5..0526d8a6af 100644
--- a/tests/topotests/bfd_ospf_topo1/rt1/step1/show_ipv6_route.ref
+++ b/tests/topotests/bfd_ospf_topo1/rt1/step1/show_ipv6_route.ref
@@ -1,7 +1,7 @@
{
- "::ffff:202:202\/128":[
+ "::ffff:2.2.2.2\/128":[
{
- "prefix":"::ffff:202:202\/128",
+ "prefix":"::ffff:2.2.2.2\/128",
"protocol":"ospf6",
"selected":true,
"destSelected":true,
@@ -16,9 +16,9 @@
]
}
],
- "::ffff:303:303\/128":[
+ "::ffff:3.3.3.3\/128":[
{
- "prefix":"::ffff:303:303\/128",
+ "prefix":"::ffff:3.3.3.3\/128",
"protocol":"ospf6",
"selected":true,
"destSelected":true,
@@ -33,9 +33,9 @@
]
}
],
- "::ffff:404:404\/128":[
+ "::ffff:4.4.4.4\/128":[
{
- "prefix":"::ffff:404:404\/128",
+ "prefix":"::ffff:4.4.4.4\/128",
"protocol":"ospf6",
"selected":true,
"destSelected":true,
@@ -50,9 +50,9 @@
]
}
],
- "::ffff:505:505\/128":[
+ "::ffff:5.5.5.5\/128":[
{
- "prefix":"::ffff:505:505\/128",
+ "prefix":"::ffff:5.5.5.5\/128",
"protocol":"ospf6",
"selected":true,
"destSelected":true,
diff --git a/tests/topotests/bfd_ospf_topo1/rt1/step3/show_ipv6_route_healthy.ref b/tests/topotests/bfd_ospf_topo1/rt1/step3/show_ipv6_route_healthy.ref
index 6465efb8b5..0526d8a6af 100644
--- a/tests/topotests/bfd_ospf_topo1/rt1/step3/show_ipv6_route_healthy.ref
+++ b/tests/topotests/bfd_ospf_topo1/rt1/step3/show_ipv6_route_healthy.ref
@@ -1,7 +1,7 @@
{
- "::ffff:202:202\/128":[
+ "::ffff:2.2.2.2\/128":[
{
- "prefix":"::ffff:202:202\/128",
+ "prefix":"::ffff:2.2.2.2\/128",
"protocol":"ospf6",
"selected":true,
"destSelected":true,
@@ -16,9 +16,9 @@
]
}
],
- "::ffff:303:303\/128":[
+ "::ffff:3.3.3.3\/128":[
{
- "prefix":"::ffff:303:303\/128",
+ "prefix":"::ffff:3.3.3.3\/128",
"protocol":"ospf6",
"selected":true,
"destSelected":true,
@@ -33,9 +33,9 @@
]
}
],
- "::ffff:404:404\/128":[
+ "::ffff:4.4.4.4\/128":[
{
- "prefix":"::ffff:404:404\/128",
+ "prefix":"::ffff:4.4.4.4\/128",
"protocol":"ospf6",
"selected":true,
"destSelected":true,
@@ -50,9 +50,9 @@
]
}
],
- "::ffff:505:505\/128":[
+ "::ffff:5.5.5.5\/128":[
{
- "prefix":"::ffff:505:505\/128",
+ "prefix":"::ffff:5.5.5.5\/128",
"protocol":"ospf6",
"selected":true,
"destSelected":true,
diff --git a/tests/topotests/bfd_ospf_topo1/rt1/step3/show_ipv6_route_rt2_down.ref b/tests/topotests/bfd_ospf_topo1/rt1/step3/show_ipv6_route_rt2_down.ref
index cfb1ef1bb6..8a8a0cd77d 100644
--- a/tests/topotests/bfd_ospf_topo1/rt1/step3/show_ipv6_route_rt2_down.ref
+++ b/tests/topotests/bfd_ospf_topo1/rt1/step3/show_ipv6_route_rt2_down.ref
@@ -1,7 +1,7 @@
{
- "::ffff:202:202\/128":[
+ "::ffff:2.2.2.2\/128":[
{
- "prefix":"::ffff:202:202\/128",
+ "prefix":"::ffff:2.2.2.2\/128",
"protocol":"ospf6",
"selected":true,
"destSelected":true,
@@ -16,9 +16,9 @@
]
}
],
- "::ffff:303:303\/128":[
+ "::ffff:3.3.3.3\/128":[
{
- "prefix":"::ffff:303:303\/128",
+ "prefix":"::ffff:3.3.3.3\/128",
"protocol":"ospf6",
"selected":true,
"destSelected":true,
@@ -33,9 +33,9 @@
]
}
],
- "::ffff:404:404\/128":[
+ "::ffff:4.4.4.4\/128":[
{
- "prefix":"::ffff:404:404\/128",
+ "prefix":"::ffff:4.4.4.4\/128",
"protocol":"ospf6",
"selected":true,
"destSelected":true,
@@ -50,9 +50,9 @@
]
}
],
- "::ffff:505:505\/128":[
+ "::ffff:5.5.5.5\/128":[
{
- "prefix":"::ffff:505:505\/128",
+ "prefix":"::ffff:5.5.5.5\/128",
"protocol":"ospf6",
"selected":true,
"destSelected":true,
diff --git a/tests/topotests/bfd_ospf_topo1/rt1/step3/show_ipv6_route_rt3_down.ref b/tests/topotests/bfd_ospf_topo1/rt1/step3/show_ipv6_route_rt3_down.ref
index 58b44da5c2..e4f056f7b5 100644
--- a/tests/topotests/bfd_ospf_topo1/rt1/step3/show_ipv6_route_rt3_down.ref
+++ b/tests/topotests/bfd_ospf_topo1/rt1/step3/show_ipv6_route_rt3_down.ref
@@ -1,7 +1,7 @@
{
- "::ffff:202:202\/128":[
+ "::ffff:2.2.2.2\/128":[
{
- "prefix":"::ffff:202:202\/128",
+ "prefix":"::ffff:2.2.2.2\/128",
"protocol":"ospf6",
"selected":true,
"destSelected":true,
@@ -16,9 +16,9 @@
]
}
],
- "::ffff:303:303\/128":[
+ "::ffff:3.3.3.3\/128":[
{
- "prefix":"::ffff:303:303\/128",
+ "prefix":"::ffff:3.3.3.3\/128",
"protocol":"ospf6",
"selected":true,
"destSelected":true,
@@ -33,9 +33,9 @@
]
}
],
- "::ffff:404:404\/128":[
+ "::ffff:4.4.4.4\/128":[
{
- "prefix":"::ffff:404:404\/128",
+ "prefix":"::ffff:4.4.4.4\/128",
"protocol":"ospf6",
"selected":true,
"destSelected":true,
@@ -50,9 +50,9 @@
]
}
],
- "::ffff:505:505\/128":[
+ "::ffff:5.5.5.5\/128":[
{
- "prefix":"::ffff:505:505\/128",
+ "prefix":"::ffff:5.5.5.5\/128",
"protocol":"ospf6",
"selected":true,
"destSelected":true,
diff --git a/tests/topotests/bfd_ospf_topo1/rt1/zebra.conf b/tests/topotests/bfd_ospf_topo1/rt1/zebra.conf
index 7e6f7881b4..bf2428e625 100644
--- a/tests/topotests/bfd_ospf_topo1/rt1/zebra.conf
+++ b/tests/topotests/bfd_ospf_topo1/rt1/zebra.conf
@@ -10,7 +10,7 @@ hostname rt1
!
interface lo
ip address 1.1.1.1/32
- ipv6 address ::ffff:0101:0101/128
+ ipv6 address ::ffff:1.1.1.1/128
!
interface eth-rt2
ip address 10.0.1.1/24
diff --git a/tests/topotests/bfd_ospf_topo1/rt2/zebra.conf b/tests/topotests/bfd_ospf_topo1/rt2/zebra.conf
index 5788e31f12..1670c20506 100644
--- a/tests/topotests/bfd_ospf_topo1/rt2/zebra.conf
+++ b/tests/topotests/bfd_ospf_topo1/rt2/zebra.conf
@@ -7,7 +7,7 @@ hostname rt2
!
interface lo
ip address 2.2.2.2/32
- ipv6 address ::ffff:0202:0202/128
+ ipv6 address ::ffff:2.2.2.2/128
!
interface eth-rt1
ip address 10.0.1.2/24
diff --git a/tests/topotests/bfd_ospf_topo1/rt3/zebra.conf b/tests/topotests/bfd_ospf_topo1/rt3/zebra.conf
index 78eac2e15a..d59085560f 100644
--- a/tests/topotests/bfd_ospf_topo1/rt3/zebra.conf
+++ b/tests/topotests/bfd_ospf_topo1/rt3/zebra.conf
@@ -7,7 +7,7 @@ hostname rt3
!
interface lo
ip address 3.3.3.3/32
- ipv6 address ::ffff:0303:0303/128
+ ipv6 address ::ffff:3.3.3.3/128
!
interface eth-rt1
ip address 10.0.2.2/24
diff --git a/tests/topotests/bfd_ospf_topo1/rt4/zebra.conf b/tests/topotests/bfd_ospf_topo1/rt4/zebra.conf
index a6cb573ed8..66121662dd 100644
--- a/tests/topotests/bfd_ospf_topo1/rt4/zebra.conf
+++ b/tests/topotests/bfd_ospf_topo1/rt4/zebra.conf
@@ -7,7 +7,7 @@ hostname rt4
!
interface lo
ip address 4.4.4.4/32
- ipv6 address ::ffff:0404:0404/128
+ ipv6 address ::ffff:4.4.4.4/128
!
interface eth-rt3
ip address 10.0.4.2/24
diff --git a/tests/topotests/bfd_ospf_topo1/rt5/zebra.conf b/tests/topotests/bfd_ospf_topo1/rt5/zebra.conf
index 33473c91a3..d3331b5b6c 100644
--- a/tests/topotests/bfd_ospf_topo1/rt5/zebra.conf
+++ b/tests/topotests/bfd_ospf_topo1/rt5/zebra.conf
@@ -7,7 +7,7 @@ hostname rt5
!
interface lo
ip address 5.5.5.5/32
- ipv6 address ::ffff:0505:0505/128
+ ipv6 address ::ffff:5.5.5.5/128
!
interface eth-rt2
ip address 10.0.3.2/24
diff --git a/tests/topotests/bgp_aigp/r1/bgpd.conf b/tests/topotests/bgp_aigp/r1/bgpd.conf
index 74a0215bc4..15621999c5 100644
--- a/tests/topotests/bgp_aigp/r1/bgpd.conf
+++ b/tests/topotests/bgp_aigp/r1/bgpd.conf
@@ -9,4 +9,20 @@ router bgp 65001
neighbor 10.0.0.3 timers 1 3
neighbor 10.0.0.3 timers connect 1
neighbor 10.0.0.3 update-source lo
+ neighbor 192.168.18.8 remote-as external
+ neighbor 192.168.18.8 timers 1 3
+ neighbor 192.168.18.8 timers connect 1
+ address-family ipv4
+ neighbor 192.168.18.8 route-map r8 out
+ exit-address-family
!
+ip prefix-list p71 seq 5 permit 10.0.0.71/32
+ip prefix-list p72 seq 5 permit 10.0.0.72/32
+!
+route-map r8 permit 10
+ match ip address prefix-list p71
+ set metric igp
+route-map r8 permit 20
+ match ip address prefix-list p72
+ set metric aigp
+exit
diff --git a/tests/topotests/bgp_aigp/r1/ospfd.conf b/tests/topotests/bgp_aigp/r1/ospfd.conf
index 38aa11d036..098bf57b03 100644
--- a/tests/topotests/bgp_aigp/r1/ospfd.conf
+++ b/tests/topotests/bgp_aigp/r1/ospfd.conf
@@ -1,6 +1,6 @@
!
interface lo
- ip ospf cost 10
+ ip ospf passive
!
interface r1-eth0
ip ospf dead-interval 4
diff --git a/tests/topotests/bgp_aigp/r1/zebra.conf b/tests/topotests/bgp_aigp/r1/zebra.conf
index 0ed22d37be..7ac4bb5de9 100644
--- a/tests/topotests/bgp_aigp/r1/zebra.conf
+++ b/tests/topotests/bgp_aigp/r1/zebra.conf
@@ -8,3 +8,6 @@ interface r1-eth0
interface r1-eth1
ip address 192.168.13.1/24
!
+interface r1-eth2
+ ip address 192.168.18.1/24
+!
diff --git a/tests/topotests/bgp_aigp/r2/bgpd.conf b/tests/topotests/bgp_aigp/r2/bgpd.conf
index 4db4687536..4539016f91 100644
--- a/tests/topotests/bgp_aigp/r2/bgpd.conf
+++ b/tests/topotests/bgp_aigp/r2/bgpd.conf
@@ -1,6 +1,7 @@
router bgp 65001
no bgp ebgp-requires-policy
no bgp network import-check
+ bgp route-reflector allow-outbound-policy
neighbor 10.0.0.1 remote-as internal
neighbor 10.0.0.1 timers 1 3
neighbor 10.0.0.1 timers connect 1
@@ -11,5 +12,6 @@ router bgp 65001
neighbor 192.168.24.4 aigp
address-family ipv4
redistribute connected
+ neighbor 10.0.0.1 next-hop-self force
exit-address-family
!
diff --git a/tests/topotests/bgp_aigp/r2/ospfd.conf b/tests/topotests/bgp_aigp/r2/ospfd.conf
index ed31941f65..106a46251d 100644
--- a/tests/topotests/bgp_aigp/r2/ospfd.conf
+++ b/tests/topotests/bgp_aigp/r2/ospfd.conf
@@ -1,6 +1,6 @@
!
interface lo
- ip ospf cost 10
+ ip ospf passive
!
interface r2-eth0
ip ospf dead-interval 4
diff --git a/tests/topotests/bgp_aigp/r3/bgpd.conf b/tests/topotests/bgp_aigp/r3/bgpd.conf
index 5ab712eaba..bdaa5cf55d 100644
--- a/tests/topotests/bgp_aigp/r3/bgpd.conf
+++ b/tests/topotests/bgp_aigp/r3/bgpd.conf
@@ -1,6 +1,7 @@
router bgp 65001
no bgp ebgp-requires-policy
no bgp network import-check
+ bgp route-reflector allow-outbound-policy
neighbor 10.0.0.1 remote-as internal
neighbor 10.0.0.1 timers 1 3
neighbor 10.0.0.1 timers connect 1
@@ -11,5 +12,6 @@ router bgp 65001
neighbor 192.168.35.5 aigp
address-family ipv4
redistribute connected
+ neighbor 10.0.0.1 next-hop-self force
exit-address-family
!
diff --git a/tests/topotests/bgp_aigp/r3/ospfd.conf b/tests/topotests/bgp_aigp/r3/ospfd.conf
index f971ad6f89..9ede3a1fab 100644
--- a/tests/topotests/bgp_aigp/r3/ospfd.conf
+++ b/tests/topotests/bgp_aigp/r3/ospfd.conf
@@ -1,6 +1,6 @@
!
interface lo
- ip ospf cost 10
+ ip ospf passive
!
interface r3-eth0
ip ospf dead-interval 4
diff --git a/tests/topotests/bgp_aigp/r4/bgpd.conf b/tests/topotests/bgp_aigp/r4/bgpd.conf
index aa88bac913..2cdf84a1b3 100644
--- a/tests/topotests/bgp_aigp/r4/bgpd.conf
+++ b/tests/topotests/bgp_aigp/r4/bgpd.conf
@@ -1,6 +1,7 @@
router bgp 65001
no bgp ebgp-requires-policy
no bgp network import-check
+ bgp route-reflector allow-outbound-policy
neighbor 192.168.24.2 remote-as internal
neighbor 192.168.24.2 timers 1 3
neighbor 192.168.24.2 timers connect 1
@@ -11,7 +12,25 @@ router bgp 65001
neighbor 10.0.0.6 timers connect 1
neighbor 10.0.0.6 update-source lo
address-family ipv4
- redistribute connected
- redistribute ospf
+ redistribute connected route-map connected-to-bgp
+ redistribute ospf route-map ospf-to-bgp
+ neighbor 192.168.24.2 route-map set-nexthop out
exit-address-family
!
+ip prefix-list p66 seq 5 permit 10.0.6.6/32
+!
+route-map ospf-to-bgp permit 10
+ match ip address prefix-list p66
+ set aigp igp-metric
+!
+! Two OSPF domains should be isolated - otherwise the connected routes
+! on r4 would be advertised to r3 (via r4 -> r6 -> r5 -> r3), and can
+! mess up bgp bestpath calculation (igp metrics for the BGP nexthops).
+!
+route-map connected-to-bgp permit 10
+ set community no-advertise
+!
+route-map set-nexthop permit 10
+ set ip next-hop peer-address
+exit
+!
diff --git a/tests/topotests/bgp_aigp/r4/ospfd.conf b/tests/topotests/bgp_aigp/r4/ospfd.conf
index c9e6796f6e..237b5e18ab 100644
--- a/tests/topotests/bgp_aigp/r4/ospfd.conf
+++ b/tests/topotests/bgp_aigp/r4/ospfd.conf
@@ -1,6 +1,6 @@
!
interface lo
- ip ospf cost 10
+ ip ospf passive
!
interface r4-eth1
ip ospf dead-interval 4
diff --git a/tests/topotests/bgp_aigp/r5/bgpd.conf b/tests/topotests/bgp_aigp/r5/bgpd.conf
index 4fde262053..3d1f5e8572 100644
--- a/tests/topotests/bgp_aigp/r5/bgpd.conf
+++ b/tests/topotests/bgp_aigp/r5/bgpd.conf
@@ -1,6 +1,7 @@
router bgp 65001
no bgp ebgp-requires-policy
no bgp network import-check
+ bgp route-reflector allow-outbound-policy
neighbor 192.168.35.3 remote-as internal
neighbor 192.168.35.3 timers 1 3
neighbor 192.168.35.3 timers connect 1
@@ -11,7 +12,18 @@ router bgp 65001
neighbor 10.0.0.6 timers connect 1
neighbor 10.0.0.6 update-source lo
address-family ipv4
- redistribute connected
- redistribute ospf
+ redistribute connected route-map connected-to-bgp
+ neighbor 192.168.35.3 route-map set-nexthop out
exit-address-family
!
+! Two OSPF domains should be isolated - otherwise the connected routes
+! on r5 would be advertised to r2 (via r5 -> r6 -> r4 -> r2), and can
+! mess up bgp bestpath calculation (igp metrics for the BGP nexthops).
+!
+route-map connected-to-bgp permit 10
+ set community no-advertise
+!
+route-map set-nexthop permit 10
+ set ip next-hop peer-address
+exit
+!
diff --git a/tests/topotests/bgp_aigp/r5/ospfd.conf b/tests/topotests/bgp_aigp/r5/ospfd.conf
index b853c74102..65a213df17 100644
--- a/tests/topotests/bgp_aigp/r5/ospfd.conf
+++ b/tests/topotests/bgp_aigp/r5/ospfd.conf
@@ -1,6 +1,6 @@
!
interface lo
- ip ospf cost 10
+ ip ospf passive
!
interface r5-eth1
ip ospf dead-interval 4
diff --git a/tests/topotests/bgp_aigp/r6/bgpd.conf b/tests/topotests/bgp_aigp/r6/bgpd.conf
index 2faae7720c..2d5f7a89ba 100644
--- a/tests/topotests/bgp_aigp/r6/bgpd.conf
+++ b/tests/topotests/bgp_aigp/r6/bgpd.conf
@@ -1,6 +1,7 @@
router bgp 65001
no bgp ebgp-requires-policy
no bgp network import-check
+ bgp route-reflector allow-outbound-policy
neighbor 10.0.0.4 remote-as internal
neighbor 10.0.0.4 timers 1 3
neighbor 10.0.0.4 timers connect 1
@@ -15,6 +16,11 @@ router bgp 65001
neighbor 192.168.67.7 timers 1 3
neighbor 192.168.67.7 timers connect 1
address-family ipv4
- redistribute ospf
+ neighbor 10.0.0.4 route-map set-nexthop out
+ neighbor 10.0.0.5 route-map set-nexthop out
exit-address-family
!
+route-map set-nexthop permit 10
+ set ip next-hop peer-address
+exit
+!
diff --git a/tests/topotests/bgp_aigp/r6/ospfd.conf b/tests/topotests/bgp_aigp/r6/ospfd.conf
index 46b2933178..89cbefa895 100644
--- a/tests/topotests/bgp_aigp/r6/ospfd.conf
+++ b/tests/topotests/bgp_aigp/r6/ospfd.conf
@@ -1,6 +1,6 @@
!
interface lo
- ip ospf cost 10
+ ip ospf passive
!
interface r6-eth0
ip ospf dead-interval 4
diff --git a/tests/topotests/bgp_aigp/r6/zebra.conf b/tests/topotests/bgp_aigp/r6/zebra.conf
index f8ca5f8b82..b6456cacc5 100644
--- a/tests/topotests/bgp_aigp/r6/zebra.conf
+++ b/tests/topotests/bgp_aigp/r6/zebra.conf
@@ -1,6 +1,7 @@
!
interface lo
ip address 10.0.0.6/32
+ ip address 10.0.6.6/32
!
interface r6-eth0
ip address 192.168.46.6/24
diff --git a/tests/topotests/bgp_aigp/r8/bgpd.conf b/tests/topotests/bgp_aigp/r8/bgpd.conf
new file mode 100644
index 0000000000..c50c3ce91a
--- /dev/null
+++ b/tests/topotests/bgp_aigp/r8/bgpd.conf
@@ -0,0 +1,4 @@
+router bgp 65008
+ no bgp ebgp-requires-policy
+ neighbor 192.168.18.1 remote-as external
+!
diff --git a/tests/topotests/bgp_aigp/r8/zebra.conf b/tests/topotests/bgp_aigp/r8/zebra.conf
new file mode 100644
index 0000000000..f7545270b2
--- /dev/null
+++ b/tests/topotests/bgp_aigp/r8/zebra.conf
@@ -0,0 +1,4 @@
+!
+interface r8-eth0
+ ip address 192.168.18.8/24
+!
diff --git a/tests/topotests/bgp_aigp/test_bgp_aigp.py b/tests/topotests/bgp_aigp/test_bgp_aigp.py
index b81c543297..f937f851a6 100644
--- a/tests/topotests/bgp_aigp/test_bgp_aigp.py
+++ b/tests/topotests/bgp_aigp/test_bgp_aigp.py
@@ -12,9 +12,13 @@ r7 sets aigp-metric for 10.0.0.71/32 to 71, and 72 for 10.0.0.72/32.
r6 receives those routes with aigp-metric TLV.
r2 and r3 receives those routes with aigp-metric TLV increased by 20,
-and 30 appropriately.
+and 10 appropriately.
-r1 receives routes with aigp-metric TLV 111,131 and 112,132 appropriately.
+r1 receives routes with aigp-metric TLV 81, 91 and 82, 92 respectively.
+
+r1 advertises MED from IGP protocol (set metric igp) to r8.
+
+r1 advertises MED from AIGP (set metric aigp) to r8.
"""
import os
@@ -34,7 +38,7 @@ pytestmark = [pytest.mark.bgpd]
def build_topo(tgen):
- for routern in range(1, 8):
+ for routern in range(1, 9):
tgen.add_router("r{}".format(routern))
switch = tgen.add_switch("s1")
@@ -65,6 +69,10 @@ def build_topo(tgen):
switch.add_link(tgen.gears["r6"])
switch.add_link(tgen.gears["r7"])
+ switch = tgen.add_switch("s8")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r8"])
+
def setup_module(mod):
tgen = Topogen(build_topo, mod.__name__)
@@ -102,21 +110,36 @@ def test_bgp_aigp():
r3 = tgen.gears["r3"]
r4 = tgen.gears["r4"]
r5 = tgen.gears["r5"]
+ r8 = tgen.gears["r8"]
def _bgp_converge():
output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast 10.0.0.71/32 json"))
expected = {
"paths": [
{
- "aigpMetric": 111,
+ "aigpMetric": 81,
"valid": True,
- "nexthops": [{"hostname": "r3", "accessible": True}],
+ "nexthops": [
+ {
+ "ip": "10.0.0.3",
+ "hostname": "r3",
+ "metric": 30,
+ "accessible": True,
+ }
+ ],
},
{
- "aigpMetric": 131,
+ "aigpMetric": 91,
"valid": True,
- "bestpath": {"selectionReason": "Neighbor IP"},
- "nexthops": [{"hostname": "r2", "accessible": True}],
+ "bestpath": {"selectionReason": "IGP Metric"},
+ "nexthops": [
+ {
+ "ip": "10.0.0.2",
+ "hostname": "r2",
+ "metric": 10,
+ "accessible": True,
+ }
+ ],
},
]
}
@@ -129,6 +152,18 @@ def test_bgp_aigp():
expected = {"paths": [{"aigpMetric": aigp, "valid": True}]}
return topotest.json_cmp(output, expected)
+ def _bgp_check_received_med():
+ output = json.loads(
+ r8.vtysh_cmd("show bgp ipv4 unicast 10.0.0.64/28 longer-prefixes json")
+ )
+ expected = {
+ "routes": {
+ "10.0.0.71/32": [{"valid": True, "metric": 10}],
+ "10.0.0.72/32": [{"valid": True, "metric": 92}],
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
def _bgp_check_aigp_metric_bestpath():
output = json.loads(
r1.vtysh_cmd(
@@ -140,30 +175,58 @@ def test_bgp_aigp():
"10.0.0.71/32": {
"paths": [
{
- "aigpMetric": 111,
- "bestpath": {"selectionReason": "AIGP"},
+ "aigpMetric": 81,
"valid": True,
- "nexthops": [{"hostname": "r3", "accessible": True}],
+ "nexthops": [
+ {
+ "ip": "10.0.0.3",
+ "hostname": "r3",
+ "metric": 30,
+ "accessible": True,
+ }
+ ],
},
{
- "aigpMetric": 131,
+ "aigpMetric": 91,
"valid": True,
- "nexthops": [{"hostname": "r2", "accessible": True}],
+ "bestpath": {"selectionReason": "AIGP"},
+ "nexthops": [
+ {
+ "ip": "10.0.0.2",
+ "hostname": "r2",
+ "metric": 10,
+ "accessible": True,
+ }
+ ],
},
],
},
"10.0.0.72/32": {
"paths": [
{
- "aigpMetric": 112,
- "bestpath": {"selectionReason": "AIGP"},
+ "aigpMetric": 82,
"valid": True,
- "nexthops": [{"hostname": "r3", "accessible": True}],
+ "nexthops": [
+ {
+ "ip": "10.0.0.3",
+ "hostname": "r3",
+ "metric": 30,
+ "accessible": True,
+ }
+ ],
},
{
- "aigpMetric": 132,
+ "aigpMetric": 92,
"valid": True,
- "nexthops": [{"hostname": "r2", "accessible": True}],
+ "bestpath": {"selectionReason": "AIGP"},
+ "nexthops": [
+ {
+ "ip": "10.0.0.2",
+ "hostname": "r2",
+ "metric": 10,
+ "accessible": True,
+ }
+ ],
},
],
},
@@ -185,6 +248,11 @@ def test_bgp_aigp():
"""
)
+ # r4, 10.0.6.6/32 with aigp-metric 20
+ test_func = functools.partial(_bgp_check_aigp_metric, r4, "10.0.6.6/32", 20)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assert result is None, "aigp-metric for 10.0.6.6/32 is not 20"
+
# r4, 10.0.0.71/32 with aigp-metric 71
test_func = functools.partial(_bgp_check_aigp_metric, r4, "10.0.0.71/32", 71)
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
@@ -195,21 +263,28 @@ def test_bgp_aigp():
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
assert result is None, "aigp-metric for 10.0.0.72/32 is not 72"
- # r2, 10.0.0.71/32 with aigp-metric 101 (71 + 30)
- test_func = functools.partial(_bgp_check_aigp_metric, r2, "10.0.0.71/32", 101)
+ # r2, 10.0.0.71/32 with aigp-metric 101 (71 + 20)
+ test_func = functools.partial(_bgp_check_aigp_metric, r2, "10.0.0.71/32", 91)
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
- assert result is None, "aigp-metric for 10.0.0.71/32 is not 101"
+ assert result is None, "aigp-metric for 10.0.0.71/32 is not 91"
- # r3, 10.0.0.72/32 with aigp-metric 92 (72 + 20)
- test_func = functools.partial(_bgp_check_aigp_metric, r3, "10.0.0.72/32", 92)
+ # r3, 10.0.0.72/32 with aigp-metric 92 (72 + 10)
+ test_func = functools.partial(_bgp_check_aigp_metric, r3, "10.0.0.72/32", 82)
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
- assert result is None, "aigp-metric for 10.0.0.72/32 is not 92"
+ assert result is None, "aigp-metric for 10.0.0.72/32 is not 82"
- # r1, check if AIGP is considered in best-path selection (lowest wins)
+ # r1, check if AIGP is considered in best-path selection (lowest wins: aigp + nexthop-metric)
test_func = functools.partial(_bgp_check_aigp_metric_bestpath)
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
assert result is None, "AIGP attribute is not considered in best-path selection"
+ # r8, check if MED is set derived from `set metric igp`, and `set metric aigp`
+ test_func = functools.partial(_bgp_check_received_med)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert (
+ result is None
+ ), "MED attribute values are not derived from `set metric [a]igp`"
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
diff --git a/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py b/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py
index 2d027081cb..9dfb7fc4d9 100644
--- a/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py
+++ b/tests/topotests/bgp_evpn_rt5/test_bgp_evpn.py
@@ -210,7 +210,7 @@ def test_protocols_convergence():
"vrfName": "r1-vrf-101",
"nexthops": [
{
- "ip": "::ffff:c0a8:6429",
+ "ip": "::ffff:192.168.100.41",
}
],
}
@@ -227,8 +227,8 @@ def test_protocols_convergence():
"192.168.100.41": {
"nexthopIp": "192.168.100.41",
},
- "::ffff:c0a8:6429": {
- "nexthopIp": "::ffff:c0a8:6429",
+ "::ffff:192.168.100.41": {
+ "nexthopIp": "::ffff:192.168.100.41",
},
}
}
diff --git a/tests/topotests/bgp_ipv4_over_ipv6/test_rfc5549_ebgp_unnumbered_nbr.py b/tests/topotests/bgp_ipv4_over_ipv6/test_rfc5549_ebgp_unnumbered_nbr.py
index 803b51c043..8382fea188 100644
--- a/tests/topotests/bgp_ipv4_over_ipv6/test_rfc5549_ebgp_unnumbered_nbr.py
+++ b/tests/topotests/bgp_ipv4_over_ipv6/test_rfc5549_ebgp_unnumbered_nbr.py
@@ -670,7 +670,7 @@ def test_configure_gua_on_unnumbered_intf(request):
{
"nexthops": [
{
- "ip": "::ffff:a00:501",
+ "ip": "::ffff:10.0.5.1",
"hostname": "r1",
"afi": "ipv6",
"scope": "global",
@@ -754,7 +754,7 @@ def test_configure_gua_on_unnumbered_intf(request):
assert (
result is None
), "Testcase {} : Failed \n Error: Nexthop for prefix 11.0.20.1 \
- is not ::ffff:a00:501".format(
+ is not ::ffff:10.0.5.1".format(
tc_name
)
diff --git a/tests/topotests/bgp_match_peer/r1/frr.conf b/tests/topotests/bgp_match_peer/r1/frr.conf
index f30da3b896..02fb8ae518 100644
--- a/tests/topotests/bgp_match_peer/r1/frr.conf
+++ b/tests/topotests/bgp_match_peer/r1/frr.conf
@@ -17,6 +17,7 @@ router bgp 65001
neighbor 192.168.1.2 route-map all in
neighbor r3 route-map all in
neighbor r4 route-map all in
+ neighbor r4 route-map r4 out
exit-address-family
!
route-map all permit 5
@@ -24,7 +25,7 @@ route-map all permit 5
set metric 1
!
route-map all permit 10
- match peer 192.168.1.2
+ match src-peer 192.168.1.2
set metric 2
!
route-map all permit 15
@@ -35,3 +36,6 @@ route-map all permit 20
match peer r4
set metric 4
!
+route-map r4 permit 10
+ match src-peer r3
+!
diff --git a/tests/topotests/bgp_match_peer/test_bgp_match_peer.py b/tests/topotests/bgp_match_peer/test_bgp_match_peer.py
index 4eb7473df0..180dbcd08a 100644
--- a/tests/topotests/bgp_match_peer/test_bgp_match_peer.py
+++ b/tests/topotests/bgp_match_peer/test_bgp_match_peer.py
@@ -82,6 +82,29 @@ def test_bgp_match_peer():
_, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
assert result is None, "Can't converge"
+ def _bgp_show_advertised_routes():
+ output = json.loads(
+ r1.vtysh_cmd("show bgp ipv4 unicast neighbors r4 advertised-routes json")
+ )
+ expected = {
+ "advertisedRoutes": {
+ "10.0.0.3/32": {
+ "network": "10.0.0.3/32",
+ "nextHop": "192.168.1.3",
+ "path": "65003",
+ }
+ },
+ "totalPrefixCounter": 1,
+ }
+
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _bgp_show_advertised_routes,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Can't filter by source peer"
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
diff --git a/tests/topotests/bgp_nexthop_ipv6/r4/show_bgp_ipv6_step2.json b/tests/topotests/bgp_nexthop_ipv6/r4/show_bgp_ipv6_step2.json
index 35a31e63f9..5506f07f29 100644
--- a/tests/topotests/bgp_nexthop_ipv6/r4/show_bgp_ipv6_step2.json
+++ b/tests/topotests/bgp_nexthop_ipv6/r4/show_bgp_ipv6_step2.json
@@ -9,13 +9,7 @@
"ip": "fd00:0:2::1",
"hostname": "rr",
"afi": "ipv6",
- "scope": "global"
- },
- {
- "ip": "link-local:rr:eth-sw",
- "hostname": "rr",
- "afi": "ipv6",
- "scope": "link-local",
+ "scope": "global",
"used": true
}
]
@@ -28,13 +22,7 @@
"ip": "fd00:0:2::2",
"hostname": "rr",
"afi": "ipv6",
- "scope": "global"
- },
- {
- "ip": "link-local:rr:eth-sw",
- "hostname": "rr",
- "afi": "ipv6",
- "scope": "link-local",
+ "scope": "global",
"used": true
}
]
@@ -47,13 +35,7 @@
"ip": "fd00:0:2::3",
"hostname": "rr",
"afi": "ipv6",
- "scope": "global"
- },
- {
- "ip": "link-local:rr:eth-sw",
- "hostname": "rr",
- "afi": "ipv6",
- "scope": "link-local",
+ "scope": "global",
"used": true
}
]
@@ -117,13 +99,7 @@
"ip": "fd00:0:2::1",
"hostname": "rr",
"afi": "ipv6",
- "scope": "global"
- },
- {
- "ip": "link-local:rr:eth-sw",
- "hostname": "rr",
- "afi": "ipv6",
- "scope": "link-local",
+ "scope": "global",
"used": true
}
]
@@ -136,13 +112,7 @@
"ip": "fd00:0:2::2",
"hostname": "rr",
"afi": "ipv6",
- "scope": "global"
- },
- {
- "ip": "link-local:rr:eth-sw",
- "hostname": "rr",
- "afi": "ipv6",
- "scope": "link-local",
+ "scope": "global",
"used": true
}
]
@@ -155,13 +125,7 @@
"ip": "fd00:0:2::3",
"hostname": "rr",
"afi": "ipv6",
- "scope": "global"
- },
- {
- "ip": "link-local:rr:eth-sw",
- "hostname": "rr",
- "afi": "ipv6",
- "scope": "link-local",
+ "scope": "global",
"used": true
}
]
diff --git a/tests/topotests/bgp_nexthop_ipv6/r5/show_bgp_ipv6_step2.json b/tests/topotests/bgp_nexthop_ipv6/r5/show_bgp_ipv6_step2.json
index d0875474ae..afcf7c3ffc 100644
--- a/tests/topotests/bgp_nexthop_ipv6/r5/show_bgp_ipv6_step2.json
+++ b/tests/topotests/bgp_nexthop_ipv6/r5/show_bgp_ipv6_step2.json
@@ -9,13 +9,7 @@
"ip": "fd00:0:3::9",
"hostname": "rr",
"afi": "ipv6",
- "scope": "global"
- },
- {
- "ip": "link-local:rr:eth-r5",
- "hostname": "rr",
- "afi": "ipv6",
- "scope": "link-local",
+ "scope": "global",
"used": true
}
]
@@ -28,13 +22,7 @@
"ip": "fd00:0:3::9",
"hostname": "rr",
"afi": "ipv6",
- "scope": "global"
- },
- {
- "ip": "link-local:rr:eth-r5",
- "hostname": "rr",
- "afi": "ipv6",
- "scope": "link-local",
+ "scope": "global",
"used": true
}
]
@@ -47,13 +35,7 @@
"ip": "fd00:0:3::9",
"hostname": "rr",
"afi": "ipv6",
- "scope": "global"
- },
- {
- "ip": "link-local:rr:eth-r5",
- "hostname": "rr",
- "afi": "ipv6",
- "scope": "link-local",
+ "scope": "global",
"used": true
}
]
@@ -117,13 +99,7 @@
"ip": "fd00:0:3::9",
"hostname": "rr",
"afi": "ipv6",
- "scope": "global"
- },
- {
- "ip": "link-local:rr:eth-r5",
- "hostname": "rr",
- "afi": "ipv6",
- "scope": "link-local",
+ "scope": "global",
"used": true
}
]
@@ -136,13 +112,7 @@
"ip": "fd00:0:3::9",
"hostname": "rr",
"afi": "ipv6",
- "scope": "global"
- },
- {
- "ip": "link-local:rr:eth-r5",
- "hostname": "rr",
- "afi": "ipv6",
- "scope": "link-local",
+ "scope": "global",
"used": true
}
]
@@ -155,13 +125,7 @@
"ip": "fd00:0:3::9",
"hostname": "rr",
"afi": "ipv6",
- "scope": "global"
- },
- {
- "ip": "link-local:rr:eth-r5",
- "hostname": "rr",
- "afi": "ipv6",
- "scope": "link-local",
+ "scope": "global",
"used": true
}
]
diff --git a/tests/topotests/bgp_set_metric_igp/__init__.py b/tests/topotests/bgp_set_metric_igp/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_set_metric_igp/__init__.py
diff --git a/tests/topotests/bgp_set_metric_igp/r1/frr.conf b/tests/topotests/bgp_set_metric_igp/r1/frr.conf
new file mode 100644
index 0000000000..018ea0269e
--- /dev/null
+++ b/tests/topotests/bgp_set_metric_igp/r1/frr.conf
@@ -0,0 +1,13 @@
+!
+int r1-eth0
+ ip address 10.0.0.1/24
+!
+int r1-eth1
+ ip address 10.0.1.1/24
+!
+router bgp 65001
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ neighbor 10.0.0.2 remote-as external
+ neighbor 10.0.1.2 remote-as external
+!
diff --git a/tests/topotests/bgp_set_metric_igp/r2/frr.conf b/tests/topotests/bgp_set_metric_igp/r2/frr.conf
new file mode 100644
index 0000000000..bce06c47f0
--- /dev/null
+++ b/tests/topotests/bgp_set_metric_igp/r2/frr.conf
@@ -0,0 +1,36 @@
+!
+int r2-eth0
+ ip address 10.0.0.2/24
+ ip router isis n2
+ isis circuit-type level-2-only
+ isis fast-reroute lfa level-2
+ isis network point-to-point
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+int r2-eth1
+ ip address 10.0.2.1/24
+ ip router isis n2
+ isis circuit-type level-2-only
+ isis fast-reroute lfa level-2
+ isis network point-to-point
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+router bgp 65002
+ no bgp ebgp-requires-policy
+ neighbor 10.0.0.1 remote-as external
+ neighbor 10.0.2.2 remote-as internal
+ address-family ipv4 unicast
+ neighbor 10.0.0.1 route-map igp out
+ exit-address-family
+!
+router isis n2
+ is-type level-2-only
+ net 49.0001.0000.0000.0002.00
+ lsp-mtu 1440
+exit
+!
+route-map igp permit 10
+ set metric igp
+exit
diff --git a/tests/topotests/bgp_set_metric_igp/r3/frr.conf b/tests/topotests/bgp_set_metric_igp/r3/frr.conf
new file mode 100644
index 0000000000..312f97d08a
--- /dev/null
+++ b/tests/topotests/bgp_set_metric_igp/r3/frr.conf
@@ -0,0 +1,38 @@
+!
+int r3-eth0
+ ip address 10.0.1.2/24
+ ip router isis n3
+ isis circuit-type level-2-only
+ isis fast-reroute lfa level-2
+ isis network point-to-point
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+int r3-eth1
+ ip address 10.0.3.1/24
+ ip router isis n3
+ isis circuit-type level-2-only
+ isis fast-reroute lfa level-2
+ isis metric level-1 10
+ isis metric level-2 100
+ isis network point-to-point
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+router bgp 65002
+ no bgp ebgp-requires-policy
+ neighbor 10.0.1.1 remote-as external
+ neighbor 10.0.3.2 remote-as internal
+ address-family ipv4 unicast
+ neighbor 10.0.1.1 route-map igp out
+ exit-address-family
+!
+router isis n3
+ is-type level-2-only
+ net 49.0001.0000.0000.0003.00
+ lsp-mtu 1440
+exit
+!
+route-map igp permit 10
+ set metric igp
+exit
diff --git a/tests/topotests/bgp_set_metric_igp/r4/frr.conf b/tests/topotests/bgp_set_metric_igp/r4/frr.conf
new file mode 100644
index 0000000000..04165b80b2
--- /dev/null
+++ b/tests/topotests/bgp_set_metric_igp/r4/frr.conf
@@ -0,0 +1,41 @@
+!
+int r4-eth0
+ ip address 10.0.2.2/24
+ ip router isis n4
+ isis circuit-type level-2-only
+ isis fast-reroute lfa level-2
+ isis network point-to-point
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+int r4-eth1
+ ip address 10.0.3.2/24
+ ip router isis n4
+ isis circuit-type level-2-only
+ isis fast-reroute lfa level-2
+ isis metric level-1 10
+ isis metric level-2 100
+ isis network point-to-point
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+int r4-eth2
+ ip address 10.0.4.1/24
+ ip router isis n4
+ isis circuit-type level-2-only
+ isis fast-reroute lfa level-2
+ isis network point-to-point
+ isis hello-interval 1
+ isis hello-multiplier 10
+!
+router bgp 65002
+ no bgp ebgp-requires-policy
+ neighbor 10.0.2.1 remote-as internal
+ neighbor 10.0.3.1 remote-as internal
+ neighbor 10.0.4.2 remote-as external
+!
+router isis n4
+ is-type level-2-only
+ net 49.0001.0000.0000.0004.00
+ lsp-mtu 1440
+exit
diff --git a/tests/topotests/bgp_set_metric_igp/r5/frr.conf b/tests/topotests/bgp_set_metric_igp/r5/frr.conf
new file mode 100644
index 0000000000..af23677b72
--- /dev/null
+++ b/tests/topotests/bgp_set_metric_igp/r5/frr.conf
@@ -0,0 +1,14 @@
+!
+int r5-eth0
+ ip address 10.0.4.2/24
+!
+router bgp 65005
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ neighbor 10.0.4.1 remote-as external
+ neighbor 10.0.4.1 timers 1 3
+ neighbor 10.0.4.1 timers connect 1
+ address-family ipv4 unicast
+ network 10.5.5.5/32
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_set_metric_igp/test_bgp_set_metric_igp.py b/tests/topotests/bgp_set_metric_igp/test_bgp_set_metric_igp.py
new file mode 100644
index 0000000000..8fbe817689
--- /dev/null
+++ b/tests/topotests/bgp_set_metric_igp/test_bgp_set_metric_igp.py
@@ -0,0 +1,146 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+# Copyright (c) 2024 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, get_topogen
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def setup_module(mod):
+ topodef = {
+ "s1": ("r1", "r2"),
+ "s2": ("r1", "r3"),
+ "s3": ("r2", "r4"),
+ "s4": ("r3", "r4"),
+ "s5": ("r4", "r5"),
+ }
+ tgen = Topogen(topodef, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for _, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_set_metric_igp():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ r2 = tgen.gears["r2"]
+
+ def _bgp_converge():
+ output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast json"))
+ expected = {
+ "routes": {
+ "10.5.5.5/32": [
+ {
+ "valid": True,
+ "bestpath": True,
+ "selectionReason": "MED",
+ "metric": 20,
+ "nexthops": [
+ {
+ "ip": "10.0.0.2",
+ "hostname": "r2",
+ }
+ ],
+ },
+ {
+ "valid": True,
+ "bestpath": None,
+ "metric": 110,
+ "nexthops": [
+ {
+ "ip": "10.0.1.2",
+ "hostname": "r3",
+ }
+ ],
+ },
+ ]
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _bgp_converge,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=120, wait=5)
+ assert result is None, "10.5.5.5/32 best path is not via r2 (MED == 20)"
+
+ r2.vtysh_cmd(
+ """
+configure terminal
+interface r2-eth1
+ isis metric level-2 6000
+"""
+ )
+
+ def _bgp_converge_after_isis_metric_changes():
+ output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast json"))
+ expected = {
+ "routes": {
+ "10.5.5.5/32": [
+ {
+ "valid": True,
+ "bestpath": None,
+ "metric": 6010,
+ "nexthops": [
+ {
+ "ip": "10.0.0.2",
+ "hostname": "r2",
+ }
+ ],
+ },
+ {
+ "valid": True,
+ "bestpath": True,
+ "selectionReason": "MED",
+ "metric": 110,
+ "nexthops": [
+ {
+ "ip": "10.0.1.2",
+ "hostname": "r3",
+ }
+ ],
+ },
+ ]
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _bgp_converge_after_isis_metric_changes,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=120, wait=5)
+ assert result is None, "10.5.5.5/32 best path is not via r3 (MED == 110)"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/lib/common_check.py b/tests/topotests/lib/common_check.py
index 19f02dbadc..b04b9de44e 100644
--- a/tests/topotests/lib/common_check.py
+++ b/tests/topotests/lib/common_check.py
@@ -58,7 +58,7 @@ def iproute2_check_path_selection(router, ipaddr_str, expected, vrf_name=None):
else:
cmdstr = f"ip -json route show {ipaddr_str}"
try:
- output = json.loads(cmdstr)
+ output = json.loads(router.cmd(cmdstr))
except:
output = []
diff --git a/tools/gcc-plugins/frr-format.c b/tools/gcc-plugins/frr-format.c
index 963741e479..d9e38f62ca 100644
--- a/tools/gcc-plugins/frr-format.c
+++ b/tools/gcc-plugins/frr-format.c
@@ -2685,7 +2685,8 @@ tree type_normalize (tree type, tree *cousin, tree target = NULL)
{
while (1)
{
- if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == POINTER_TYPE)
+ if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == POINTER_TYPE
+ || TREE_CODE (type) == ARRAY_TYPE)
return type;
if (target)
/* Strip off any "const" etc. */
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 2d80feef6c..5a54c60c6b 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -280,9 +280,6 @@ static int vtysh_client_run(struct vtysh_client *vclient, const char *line,
nread = vtysh_client_receive(
vclient, bufvalid, buf + bufsz - bufvalid - 1, pass_fd);
- if (nread < 0 && (errno == EINTR || errno == EAGAIN))
- continue;
-
if (nread <= 0) {
if (vty->of)
vty_out(vty,
@@ -698,7 +695,7 @@ static char *trim(char *s)
int vtysh_mark_file(const char *filename)
{
struct vty *vty;
- FILE *confp = NULL;
+ FILE *confp = NULL, *closefp = NULL;
int ret;
vector vline;
int tried = 0;
@@ -711,7 +708,7 @@ int vtysh_mark_file(const char *filename)
if (strncmp("-", filename, 1) == 0)
confp = stdin;
else
- confp = fopen(filename, "r");
+ confp = closefp = fopen(filename, "r");
if (confp == NULL) {
fprintf(stderr, "%% Can't open config file %s due to '%s'.\n",
@@ -851,9 +848,8 @@ int vtysh_mark_file(const char *filename)
vty_close(vty);
XFREE(MTYPE_VTYSH_CMD, vty_buf_copy);
- if (confp != stdin)
- fclose(confp);
-
+ if (closefp)
+ fclose(closefp);
return 0;
}
diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c
index 64198132cc..297d87ec41 100644
--- a/vtysh/vtysh_main.c
+++ b/vtysh/vtysh_main.c
@@ -350,6 +350,7 @@ int main(int argc, char **argv, char **env)
char pathspace[MAXPATHLEN] = "";
const char *histfile = NULL;
const char *histfile_env = getenv("VTYSH_HISTFILE");
+ const char *logpath = getenv("VTYSH_LOG");
/* SUID: drop down to calling user & go back up when needed */
elevuid = geteuid();
@@ -643,9 +644,7 @@ int main(int argc, char **argv, char **env)
}
}
- if (getenv("VTYSH_LOG")) {
- const char *logpath = getenv("VTYSH_LOG");
-
+ if (logpath != NULL) {
logfile = fopen(logpath, "a");
if (!logfile) {
fprintf(stderr, "Failed to open logfile (%s): %s\n",
diff --git a/yang/frr-bgp-route-map.yang b/yang/frr-bgp-route-map.yang
index 44058ab04e..4ed80d7d07 100644
--- a/yang/frr-bgp-route-map.yang
+++ b/yang/frr-bgp-route-map.yang
@@ -94,6 +94,12 @@ module frr-bgp-route-map {
"Match peer address";
}
+ identity src-peer {
+ base frr-route-map:rmap-match-type;
+ description
+ "Match source peer address";
+ }
+
identity mac-address-list {
base frr-route-map:rmap-match-type;
description
@@ -688,6 +694,37 @@ identity set-extcommunity-color {
}
}
+ case src-peer {
+ when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:src-peer')";
+ choice peer {
+ description
+ "Value of the peer";
+ case src-peer-ipv4-address {
+ description
+ "IP address of peer";
+ leaf src-peer-ipv4-address {
+ type inet:ipv4-address;
+ }
+ }
+
+ case src-peer-interface {
+ description
+ "Interface name of peer";
+ leaf src-peer-interface {
+ type string;
+ }
+ }
+
+ case src-peer-ipv6-address {
+ description
+ "IPv6 address of peer";
+ leaf src-peer-ipv6-address {
+ type inet:ipv6-address;
+ }
+ }
+ }
+ }
+
case access-list-name {
when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:mac-address-list') or "
+ "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:as-path-list') or "
diff --git a/yang/frr-route-map.yang b/yang/frr-route-map.yang
index c875a6ec7f..244c353a63 100644
--- a/yang/frr-route-map.yang
+++ b/yang/frr-route-map.yang
@@ -355,6 +355,22 @@ module frr-route-map {
"Subtract round trip time to metric";
}
}
+
+ case use-igp {
+ leaf use-igp {
+ type boolean;
+ description
+ "Use metric from IGP procotol";
+ }
+ }
+
+ case use-aigp {
+ leaf use-aigp {
+ type boolean;
+ description
+ "Use metric from AIGP (Accumulated IGP)";
+ }
+ }
}
}
diff --git a/zebra/connected.c b/zebra/connected.c
index 974a1c17a2..ce4f6919d5 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -176,6 +176,43 @@ static void connected_update(struct interface *ifp, struct connected *ifc)
connected_announce(ifp, ifc);
}
+/*
+ * This function goes through and handles the deletion of a kernel route that happened
+ * to be the exact same as the connected route, so that the connected route wins.
+ * This can happen during processing if we happen to receive events in a slightly
+ * unexpected order. This is similiar to code in the other direction where if we
+ * have a kernel route don't install it if it perfectly matches a connected route.
+ */
+static void connected_remove_kernel_for_connected(afi_t afi, safi_t safi, struct zebra_vrf *zvrf,
+ struct prefix *p, struct nexthop *nh)
+{
+ struct route_node *rn;
+ struct route_entry *re;
+ rib_dest_t *dest;
+ struct route_table *table = zebra_vrf_table(afi, SAFI_UNICAST, zvrf->vrf->vrf_id);
+
+ if (!table)
+ return;
+
+ rn = route_node_match(table, p);
+ if (!rn)
+ return;
+
+ if (!prefix_same(&rn->p, p))
+ return;
+
+ dest = rib_dest_from_rnode(rn);
+ if (!dest || !dest->selected_fib)
+ return;
+
+ re = dest->selected_fib;
+ if (re->type != ZEBRA_ROUTE_KERNEL)
+ return;
+
+ rib_delete(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_KERNEL, 0, 0, p, NULL, nh, 0,
+ zvrf->table_id, 0, 0, false);
+}
+
/* Called from if_up(). */
void connected_up(struct interface *ifp, struct connected *ifc)
{
@@ -284,10 +321,13 @@ void connected_up(struct interface *ifp, struct connected *ifc)
}
if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_NOPREFIXROUTE)) {
+ connected_remove_kernel_for_connected(afi, SAFI_UNICAST, zvrf, &p, &nh);
+
rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id,
ZEBRA_ROUTE_CONNECT, 0, flags, &p, NULL, &nh, 0,
zvrf->table_id, metric, 0, 0, 0, false);
+ connected_remove_kernel_for_connected(afi, SAFI_MULTICAST, zvrf, &p, &nh);
rib_add(afi, SAFI_MULTICAST, zvrf->vrf->vrf_id,
ZEBRA_ROUTE_CONNECT, 0, flags, &p, NULL, &nh, 0,
zvrf->table_id, metric, 0, 0, 0, false);
diff --git a/zebra/dpdk/zebra_dplane_dpdk.c b/zebra/dpdk/zebra_dplane_dpdk.c
index 411155167f..ae1a3743ce 100644
--- a/zebra/dpdk/zebra_dplane_dpdk.c
+++ b/zebra/dpdk/zebra_dplane_dpdk.c
@@ -400,6 +400,7 @@ static void zd_dpdk_rule_update(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_INTF_INSTALL:
case DPLANE_OP_INTF_UPDATE:
case DPLANE_OP_INTF_DELETE:
+ case DPLANE_OP_VLAN_INSTALL,
break;
}
}
@@ -459,6 +460,7 @@ static void zd_dpdk_process_update(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_INTF_INSTALL:
case DPLANE_OP_INTF_UPDATE:
case DPLANE_OP_INTF_DELETE:
+ case DPLANE_OP_VLAN_INSTALL,
atomic_fetch_add_explicit(&dpdk_stat->ignored_updates, 1,
memory_order_relaxed);
diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c
index 4fb57d84d9..8a967978cb 100644
--- a/zebra/dplane_fpm_nl.c
+++ b/zebra/dplane_fpm_nl.c
@@ -1058,6 +1058,7 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx)
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
case DPLANE_OP_NONE:
case DPLANE_OP_STARTUP_STAGE:
+ case DPLANE_OP_VLAN_INSTALL:
break;
}
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 8beae125d2..62b665682f 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -1610,68 +1610,18 @@ int netlink_tunneldump_read(struct zebra_ns *zns)
return 0;
}
-static const char *port_state2str(uint8_t state)
+static uint8_t netlink_get_dplane_vlan_state(uint8_t state)
{
- switch (state) {
- case BR_STATE_DISABLED:
- return "DISABLED";
- case BR_STATE_LISTENING:
- return "LISTENING";
- case BR_STATE_LEARNING:
- return "LEARNING";
- case BR_STATE_FORWARDING:
- return "FORWARDING";
- case BR_STATE_BLOCKING:
- return "BLOCKING";
- }
-
- return "UNKNOWN";
-}
-
-static void vxlan_vni_state_change(struct zebra_if *zif, uint16_t id,
- uint8_t state)
-{
- struct zebra_vxlan_vni *vnip;
-
- vnip = zebra_vxlan_if_vlanid_vni_find(zif, id);
-
- if (!vnip) {
- if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug(
- "Cannot find VNI for VID (%u) IF %s for vlan state update",
- id, zif->ifp->name);
-
- return;
- }
-
- switch (state) {
- case BR_STATE_FORWARDING:
- zebra_vxlan_if_vni_up(zif->ifp, vnip);
- break;
- case BR_STATE_BLOCKING:
- zebra_vxlan_if_vni_down(zif->ifp, vnip);
- break;
- case BR_STATE_DISABLED:
- case BR_STATE_LISTENING:
- case BR_STATE_LEARNING:
- default:
- /* Not used for anything at the moment */
- break;
- }
-}
-
-static void vlan_id_range_state_change(struct interface *ifp, uint16_t id_start,
- uint16_t id_end, uint8_t state)
-{
- struct zebra_if *zif;
-
- zif = (struct zebra_if *)ifp->info;
-
- if (!zif)
- return;
-
- for (uint16_t i = id_start; i <= id_end; i++)
- vxlan_vni_state_change(zif, i, state);
+ if (state == BR_STATE_LISTENING)
+ return ZEBRA_DPLANE_BR_STATE_LISTENING;
+ else if (state == BR_STATE_LEARNING)
+ return ZEBRA_DPLANE_BR_STATE_LEARNING;
+ else if (state == BR_STATE_FORWARDING)
+ return ZEBRA_DPLANE_BR_STATE_FORWARDING;
+ else if (state == BR_STATE_BLOCKING)
+ return ZEBRA_DPLANE_BR_STATE_BLOCKING;
+
+ return ZEBRA_DPLANE_BR_STATE_DISABLED;
}
/**
@@ -1686,7 +1636,6 @@ static void vlan_id_range_state_change(struct interface *ifp, uint16_t id_start,
int netlink_vlan_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
{
int len, rem;
- struct interface *ifp;
struct br_vlan_msg *bvm;
struct bridge_vlan_info *vinfo;
struct rtattr *vtb[BRIDGE_VLANDB_ENTRY_MAX + 1] = {};
@@ -1694,6 +1643,9 @@ int netlink_vlan_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
uint8_t state;
uint32_t vrange;
int type;
+ uint32_t count = 0;
+ struct zebra_dplane_ctx *ctx = NULL;
+ struct zebra_vxlan_vlan_array *vlan_array = NULL;
/* We only care about state changes for now */
if (!(h->nlmsg_type == RTM_NEWVLAN))
@@ -1713,25 +1665,10 @@ int netlink_vlan_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if (bvm->family != AF_BRIDGE)
return 0;
- ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), bvm->ifindex);
- if (!ifp) {
- zlog_debug("Cannot find bridge-vlan IF (%u) for vlan update",
- bvm->ifindex);
- return 0;
- }
-
- if (!IS_ZEBRA_IF_VXLAN(ifp)) {
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("Ignoring non-vxlan IF (%s) for vlan update",
- ifp->name);
-
- return 0;
- }
-
- if (IS_ZEBRA_DEBUG_KERNEL || IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("%s %s IF %s NS %u",
- nl_msg_type_to_str(h->nlmsg_type),
- nl_family_to_str(bvm->family), ifp->name, ns_id);
+ ctx = dplane_ctx_alloc();
+ dplane_ctx_set_ns_id(ctx, ns_id);
+ dplane_ctx_set_op(ctx, DPLANE_OP_VLAN_INSTALL);
+ dplane_ctx_set_vlan_ifindex(ctx, bvm->ifindex);
/* Loop over "ALL" BRIDGE_VLANDB_ENTRY */
rem = len;
@@ -1762,26 +1699,39 @@ int netlink_vlan_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if (!vtb[BRIDGE_VLANDB_ENTRY_STATE])
continue;
+ count++;
+ vlan_array =
+ XREALLOC(MTYPE_VLAN_CHANGE_ARR, vlan_array,
+ sizeof(struct zebra_vxlan_vlan_array) +
+ count * sizeof(struct zebra_vxlan_vlan));
+
+ memset(&vlan_array->vlans[count - 1], 0,
+ sizeof(struct zebra_vxlan_vlan));
+
state = *(uint8_t *)RTA_DATA(vtb[BRIDGE_VLANDB_ENTRY_STATE]);
if (vtb[BRIDGE_VLANDB_ENTRY_RANGE])
vrange = *(uint32_t *)RTA_DATA(
vtb[BRIDGE_VLANDB_ENTRY_RANGE]);
- if (IS_ZEBRA_DEBUG_KERNEL || IS_ZEBRA_DEBUG_VXLAN) {
- if (vrange)
- zlog_debug("VLANDB_ENTRY: VID (%u-%u) state=%s",
- vinfo->vid, vrange,
- port_state2str(state));
- else
- zlog_debug("VLANDB_ENTRY: VID (%u) state=%s",
- vinfo->vid, port_state2str(state));
- }
-
- vlan_id_range_state_change(
- ifp, vinfo->vid, (vrange ? vrange : vinfo->vid), state);
+ vlan_array->vlans[count - 1].state =
+ netlink_get_dplane_vlan_state(state);
+ vlan_array->vlans[count - 1].vid = vinfo->vid;
+ vlan_array->vlans[count - 1].vrange = vrange;
}
+ if (count) {
+ vlan_array->count = count;
+ dplane_ctx_set_vxlan_vlan_array(ctx, vlan_array);
+ if (IS_ZEBRA_DEBUG_KERNEL || IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("RTM_NEWVLAN for ifindex %u NS %u, enqueuing for zebra main",
+ bvm->ifindex, ns_id);
+
+ dplane_provider_enqueue_to_zebra(ctx);
+ } else
+ dplane_ctx_fini(&ctx);
+
+
return 0;
}
diff --git a/zebra/ipforward_proc.c b/zebra/ipforward_proc.c
index 08fbfede42..0eae221e1e 100644
--- a/zebra/ipforward_proc.c
+++ b/zebra/ipforward_proc.c
@@ -17,10 +17,15 @@ extern struct zebra_privs_t zserv_privs;
static const char proc_net_snmp[] = "/proc/net/snmp";
-static void dropline(FILE *fp)
+static bool dropline(FILE *fp)
{
- while (getc(fp) != '\n')
- ;
+ int ch;
+
+ do {
+ ch = getc(fp);
+ } while (ch != EOF && ch != '\n');
+
+ return ch != EOF;
}
int ipforward(void)
@@ -36,7 +41,10 @@ int ipforward(void)
return -1;
/* We don't care about the first line. */
- dropline(fp);
+ if (!dropline(fp)) {
+ fclose(fp);
+ return 0;
+ }
/* Get ip_statistics.IpForwarding :
1 => ip forwarding enabled
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index 84aabc4254..3547314f84 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -430,10 +430,6 @@ static int netlink_information_fetch(struct nlmsghdr *h, ns_id_t ns_id,
case RTM_NEWTFILTER:
case RTM_DELTFILTER:
return netlink_tfilter_change(h, ns_id, startup);
- case RTM_NEWVLAN:
- return netlink_vlan_change(h, ns_id, startup);
- case RTM_DELVLAN:
- return netlink_vlan_change(h, ns_id, startup);
/* Messages we may receive, but ignore */
case RTM_NEWCHAIN:
@@ -449,6 +445,8 @@ static int netlink_information_fetch(struct nlmsghdr *h, ns_id_t ns_id,
case RTM_NEWTUNNEL:
case RTM_DELTUNNEL:
case RTM_GETTUNNEL:
+ case RTM_NEWVLAN:
+ case RTM_DELVLAN:
return 0;
default:
/*
@@ -492,6 +490,10 @@ static int dplane_netlink_information_fetch(struct nlmsghdr *h, ns_id_t ns_id,
case RTM_DELLINK:
return netlink_link_change(h, ns_id, startup);
+ case RTM_NEWVLAN:
+ case RTM_DELVLAN:
+ return netlink_vlan_change(h, ns_id, startup);
+
default:
break;
}
@@ -1621,6 +1623,7 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth,
case DPLANE_OP_IPSET_ENTRY_ADD:
case DPLANE_OP_IPSET_ENTRY_DELETE:
case DPLANE_OP_STARTUP_STAGE:
+ case DPLANE_OP_VLAN_INSTALL:
return FRR_NETLINK_ERROR;
case DPLANE_OP_GRE_SET:
@@ -1862,8 +1865,8 @@ void kernel_init(struct zebra_ns *zns)
* setsockopt multicast group subscriptions that don't fit in nl_groups
*/
grp = RTNLGRP_BRVLAN;
- ret = setsockopt(zns->netlink.sock, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
- &grp, sizeof(grp));
+ ret = setsockopt(zns->netlink_dplane_in.sock, SOL_NETLINK,
+ NETLINK_ADD_MEMBERSHIP, &grp, sizeof(grp));
if (ret < 0)
zlog_notice(
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index 5cfbe7a896..4789cb62f2 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -1627,6 +1627,7 @@ void kernel_update_multi(struct dplane_ctx_list_head *ctx_list)
case DPLANE_OP_INTF_ADDR_DEL:
case DPLANE_OP_STARTUP_STAGE:
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
+ case DPLANE_OP_VLAN_INSTALL:
zlog_err("Unhandled dplane data for %s",
dplane_op2str(dplane_ctx_get_op(ctx)));
res = ZEBRA_DPLANE_REQUEST_FAILURE;
diff --git a/zebra/main.c b/zebra/main.c
index 687da70cab..dd6249eff5 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -238,7 +238,7 @@ void zebra_finalize(struct event *dummy)
zebra_ns_notify_close();
/* Final shutdown of ns resources */
- ns_walk_func(zebra_ns_final_shutdown, NULL, NULL);
+ ns_walk_func(zebra_ns_kernel_shutdown, NULL, NULL);
zebra_rib_terminate();
zebra_router_terminate();
@@ -251,6 +251,8 @@ void zebra_finalize(struct event *dummy)
label_manager_terminate();
+ ns_walk_func(zebra_ns_final_shutdown, NULL, NULL);
+
ns_terminate();
frr_fini();
exit(0);
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 7dae75bacc..10acee9be4 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -647,7 +647,7 @@ static int zsend_nexthop_lookup_mrib(struct zserv *client, struct ipaddr *addr,
{
struct stream *s;
unsigned long nump;
- uint8_t num;
+ uint16_t num;
struct nexthop *nexthop;
/* Get output stream. */
@@ -667,7 +667,7 @@ static int zsend_nexthop_lookup_mrib(struct zserv *client, struct ipaddr *addr,
/* remember position for nexthop_num */
nump = stream_get_endp(s);
/* reserve room for nexthop_num */
- stream_putc(s, 0);
+ stream_putw(s, 0);
nhg = rib_get_fib_nhg(re);
for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
if (rnh_nexthop_valid(re, nexthop))
@@ -675,11 +675,11 @@ static int zsend_nexthop_lookup_mrib(struct zserv *client, struct ipaddr *addr,
}
/* store nexthop_num */
- stream_putc_at(s, nump, num);
+ stream_putw_at(s, nump, num);
} else {
stream_putc(s, 0); /* distance */
stream_putl(s, 0); /* metric */
- stream_putc(s, 0); /* nexthop_num */
+ stream_putw(s, 0); /* nexthop_num */
}
stream_putw_at(s, 0, stream_get_endp(s));
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 00e990e856..88c1a04938 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -35,6 +35,8 @@ DEFINE_MTYPE_STATIC(ZEBRA, DP_PROV, "Zebra DPlane Provider");
DEFINE_MTYPE_STATIC(ZEBRA, DP_NETFILTER, "Zebra Netfilter Internal Object");
DEFINE_MTYPE_STATIC(ZEBRA, DP_NS, "DPlane NSes");
+DEFINE_MTYPE(ZEBRA, VLAN_CHANGE_ARR, "Vlan Change Array");
+
#ifndef AOK
# define AOK 0
#endif
@@ -371,6 +373,14 @@ struct dplane_srv6_encap_ctx {
};
/*
+ * VLAN info for the dataplane
+ */
+struct dplane_vlan_info {
+ ifindex_t ifindex;
+ struct zebra_vxlan_vlan_array *vlan_array;
+};
+
+/*
* The context block used to exchange info about route updates across
* the boundary between the zebra main context (and pthread) and the
* dataplane layer (and pthread).
@@ -416,6 +426,7 @@ struct zebra_dplane_ctx {
struct dplane_pw_info pw;
struct dplane_br_port_info br_port;
struct dplane_intf_info intf;
+ struct dplane_vlan_info vlan_info;
struct dplane_mac_info macinfo;
struct dplane_neigh_info neigh;
struct dplane_rule_info rule;
@@ -885,6 +896,11 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_STARTUP_STAGE:
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
break;
+ case DPLANE_OP_VLAN_INSTALL:
+ if (ctx->u.vlan_info.vlan_array)
+ XFREE(MTYPE_VLAN_CHANGE_ARR,
+ ctx->u.vlan_info.vlan_array);
+ break;
}
}
@@ -1030,144 +1046,102 @@ enum dplane_op_e dplane_ctx_get_op(const struct zebra_dplane_ctx *ctx)
const char *dplane_op2str(enum dplane_op_e op)
{
- const char *ret = "UNKNOWN";
-
switch (op) {
case DPLANE_OP_NONE:
- ret = "NONE";
- break;
+ return "NONE";
/* Route update */
case DPLANE_OP_ROUTE_INSTALL:
- ret = "ROUTE_INSTALL";
- break;
+ return "ROUTE_INSTALL";
case DPLANE_OP_ROUTE_UPDATE:
- ret = "ROUTE_UPDATE";
- break;
+ return "ROUTE_UPDATE";
case DPLANE_OP_ROUTE_DELETE:
- ret = "ROUTE_DELETE";
- break;
+ return "ROUTE_DELETE";
case DPLANE_OP_ROUTE_NOTIFY:
- ret = "ROUTE_NOTIFY";
- break;
+ return "ROUTE_NOTIFY";
/* Nexthop update */
case DPLANE_OP_NH_INSTALL:
- ret = "NH_INSTALL";
- break;
+ return "NH_INSTALL";
case DPLANE_OP_NH_UPDATE:
- ret = "NH_UPDATE";
- break;
+ return "NH_UPDATE";
case DPLANE_OP_NH_DELETE:
- ret = "NH_DELETE";
- break;
+ return "NH_DELETE";
case DPLANE_OP_LSP_INSTALL:
- ret = "LSP_INSTALL";
- break;
+ return "LSP_INSTALL";
case DPLANE_OP_LSP_UPDATE:
- ret = "LSP_UPDATE";
- break;
+ return "LSP_UPDATE";
case DPLANE_OP_LSP_DELETE:
- ret = "LSP_DELETE";
- break;
+ return "LSP_DELETE";
case DPLANE_OP_LSP_NOTIFY:
- ret = "LSP_NOTIFY";
- break;
+ return "LSP_NOTIFY";
case DPLANE_OP_PW_INSTALL:
- ret = "PW_INSTALL";
- break;
+ return "PW_INSTALL";
case DPLANE_OP_PW_UNINSTALL:
- ret = "PW_UNINSTALL";
- break;
+ return "PW_UNINSTALL";
case DPLANE_OP_SYS_ROUTE_ADD:
- ret = "SYS_ROUTE_ADD";
- break;
+ return "SYS_ROUTE_ADD";
case DPLANE_OP_SYS_ROUTE_DELETE:
- ret = "SYS_ROUTE_DEL";
- break;
+ return "SYS_ROUTE_DEL";
case DPLANE_OP_BR_PORT_UPDATE:
- ret = "BR_PORT_UPDATE";
- break;
+ return "BR_PORT_UPDATE";
case DPLANE_OP_ADDR_INSTALL:
- ret = "ADDR_INSTALL";
- break;
+ return "ADDR_INSTALL";
case DPLANE_OP_ADDR_UNINSTALL:
- ret = "ADDR_UNINSTALL";
- break;
+ return "ADDR_UNINSTALL";
case DPLANE_OP_MAC_INSTALL:
- ret = "MAC_INSTALL";
- break;
+ return "MAC_INSTALL";
case DPLANE_OP_MAC_DELETE:
- ret = "MAC_DELETE";
- break;
+ return "MAC_DELETE";
case DPLANE_OP_NEIGH_INSTALL:
- ret = "NEIGH_INSTALL";
- break;
+ return "NEIGH_INSTALL";
case DPLANE_OP_NEIGH_UPDATE:
- ret = "NEIGH_UPDATE";
- break;
+ return "NEIGH_UPDATE";
case DPLANE_OP_NEIGH_DELETE:
- ret = "NEIGH_DELETE";
- break;
+ return "NEIGH_DELETE";
case DPLANE_OP_VTEP_ADD:
- ret = "VTEP_ADD";
- break;
+ return "VTEP_ADD";
case DPLANE_OP_VTEP_DELETE:
- ret = "VTEP_DELETE";
- break;
+ return "VTEP_DELETE";
case DPLANE_OP_RULE_ADD:
- ret = "RULE_ADD";
- break;
+ return "RULE_ADD";
case DPLANE_OP_RULE_DELETE:
- ret = "RULE_DELETE";
- break;
+ return "RULE_DELETE";
case DPLANE_OP_RULE_UPDATE:
- ret = "RULE_UPDATE";
- break;
+ return "RULE_UPDATE";
case DPLANE_OP_NEIGH_DISCOVER:
- ret = "NEIGH_DISCOVER";
- break;
+ return "NEIGH_DISCOVER";
case DPLANE_OP_IPTABLE_ADD:
- ret = "IPTABLE_ADD";
- break;
+ return "IPTABLE_ADD";
case DPLANE_OP_IPTABLE_DELETE:
- ret = "IPTABLE_DELETE";
- break;
+ return "IPTABLE_DELETE";
case DPLANE_OP_IPSET_ADD:
- ret = "IPSET_ADD";
- break;
+ return "IPSET_ADD";
case DPLANE_OP_IPSET_DELETE:
- ret = "IPSET_DELETE";
- break;
+ return "IPSET_DELETE";
case DPLANE_OP_IPSET_ENTRY_ADD:
- ret = "IPSET_ENTRY_ADD";
- break;
+ return "IPSET_ENTRY_ADD";
case DPLANE_OP_IPSET_ENTRY_DELETE:
- ret = "IPSET_ENTRY_DELETE";
- break;
+ return "IPSET_ENTRY_DELETE";
case DPLANE_OP_NEIGH_IP_INSTALL:
- ret = "NEIGH_IP_INSTALL";
- break;
+ return "NEIGH_IP_INSTALL";
case DPLANE_OP_NEIGH_IP_DELETE:
- ret = "NEIGH_IP_DELETE";
- break;
+ return "NEIGH_IP_DELETE";
case DPLANE_OP_NEIGH_TABLE_UPDATE:
- ret = "NEIGH_TABLE_UPDATE";
- break;
+ return "NEIGH_TABLE_UPDATE";
case DPLANE_OP_GRE_SET:
- ret = "GRE_SET";
- break;
+ return "GRE_SET";
case DPLANE_OP_INTF_ADDR_ADD:
return "INTF_ADDR_ADD";
@@ -1179,68 +1153,53 @@ const char *dplane_op2str(enum dplane_op_e op)
return "INTF_NETCONFIG";
case DPLANE_OP_INTF_INSTALL:
- ret = "INTF_INSTALL";
- break;
+ return "INTF_INSTALL";
case DPLANE_OP_INTF_UPDATE:
- ret = "INTF_UPDATE";
- break;
+ return "INTF_UPDATE";
case DPLANE_OP_INTF_DELETE:
- ret = "INTF_DELETE";
- break;
+ return "INTF_DELETE";
case DPLANE_OP_TC_QDISC_INSTALL:
- ret = "TC_QDISC_INSTALL";
- break;
+ return "TC_QDISC_INSTALL";
case DPLANE_OP_TC_QDISC_UNINSTALL:
- ret = "TC_QDISC_UNINSTALL";
- break;
+ return "TC_QDISC_UNINSTALL";
case DPLANE_OP_TC_CLASS_ADD:
- ret = "TC_CLASS_ADD";
- break;
+ return "TC_CLASS_ADD";
case DPLANE_OP_TC_CLASS_DELETE:
- ret = "TC_CLASS_DELETE";
- break;
+ return "TC_CLASS_DELETE";
case DPLANE_OP_TC_CLASS_UPDATE:
- ret = "TC_CLASS_UPDATE";
- break;
+ return "TC_CLASS_UPDATE";
case DPLANE_OP_TC_FILTER_ADD:
- ret = "TC_FILTER_ADD";
- break;
+ return "TC_FILTER_ADD";
case DPLANE_OP_TC_FILTER_DELETE:
- ret = "TC_FILTER_DELETE";
- break;
+ return "TC_FILTER_DELETE";
case DPLANE_OP_TC_FILTER_UPDATE:
- ret = "TC__FILTER_UPDATE";
- break;
+ return "TC__FILTER_UPDATE";
case DPLANE_OP_STARTUP_STAGE:
- ret = "STARTUP_STAGE";
- break;
+ return "STARTUP_STAGE";
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
- ret = "SRV6_ENCAP_SRCADDR_SET";
- break;
+ return "SRV6_ENCAP_SRCADDR_SET";
+
+ case DPLANE_OP_VLAN_INSTALL:
+ return "NEW_VLAN";
}
- return ret;
+ return "UNKNOWN";
}
const char *dplane_res2str(enum zebra_dplane_result res)
{
- const char *ret = "<Unknown>";
-
switch (res) {
case ZEBRA_DPLANE_REQUEST_FAILURE:
- ret = "FAILURE";
- break;
+ return "FAILURE";
case ZEBRA_DPLANE_REQUEST_QUEUED:
- ret = "QUEUED";
- break;
+ return "QUEUED";
case ZEBRA_DPLANE_REQUEST_SUCCESS:
- ret = "SUCCESS";
- break;
+ return "SUCCESS";
}
- return ret;
+ return "<Unknown>";
}
void dplane_ctx_set_dest(struct zebra_dplane_ctx *ctx,
@@ -3321,6 +3280,35 @@ uint32_t dplane_get_in_queue_len(void)
memory_order_seq_cst);
}
+void dplane_ctx_set_vlan_ifindex(struct zebra_dplane_ctx *ctx, ifindex_t ifindex)
+{
+ DPLANE_CTX_VALID(ctx);
+ ctx->u.vlan_info.ifindex = ifindex;
+}
+
+ifindex_t dplane_ctx_get_vlan_ifindex(struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.vlan_info.ifindex;
+}
+
+void dplane_ctx_set_vxlan_vlan_array(struct zebra_dplane_ctx *ctx,
+ struct zebra_vxlan_vlan_array *vlan_array)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ ctx->u.vlan_info.vlan_array = vlan_array;
+}
+
+const struct zebra_vxlan_vlan_array *
+dplane_ctx_get_vxlan_vlan_array(struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.vlan_info.vlan_array;
+}
+
/*
* Internal helper that copies information from a zebra ns object; this is
* called in the zebra main pthread context as part of dplane ctx init.
@@ -6720,6 +6708,12 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
dplane_op2str(dplane_ctx_get_op(ctx)),
&ctx->u.srv6_encap.srcaddr);
break;
+
+ case DPLANE_OP_VLAN_INSTALL:
+ zlog_debug("Dplane %s on idx %u",
+ dplane_op2str(dplane_ctx_get_op(ctx)),
+ dplane_ctx_get_vlan_ifindex(ctx));
+ break;
}
}
@@ -6888,6 +6882,7 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_INTF_ADDR_ADD:
case DPLANE_OP_INTF_ADDR_DEL:
case DPLANE_OP_INTF_NETCONFIG:
+ case DPLANE_OP_VLAN_INSTALL:
break;
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index a3318bf5e9..285b00c9b7 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -24,6 +24,8 @@
extern "C" {
#endif
+DECLARE_MTYPE(VLAN_CHANGE_ARR);
+
/* Retrieve the dataplane API version number; see libfrr.h to decode major,
* minor, sub version values.
* Plugins should pay attention to the major version number, at least, to
@@ -204,6 +206,9 @@ enum dplane_op_e {
DPLANE_OP_TC_FILTER_DELETE,
DPLANE_OP_TC_FILTER_UPDATE,
+ /* VLAN update */
+ DPLANE_OP_VLAN_INSTALL,
+
/* Startup Control */
DPLANE_OP_STARTUP_STAGE,
@@ -211,6 +216,13 @@ enum dplane_op_e {
DPLANE_OP_SRV6_ENCAP_SRCADDR_SET,
};
+/* Operational status of Bridge Ports */
+#define ZEBRA_DPLANE_BR_STATE_DISABLED 0x01
+#define ZEBRA_DPLANE_BR_STATE_LISTENING 0x02
+#define ZEBRA_DPLANE_BR_STATE_LEARNING 0x04
+#define ZEBRA_DPLANE_BR_STATE_FORWARDING 0x08
+#define ZEBRA_DPLANE_BR_STATE_BLOCKING 0x10
+
/*
* The vxlan/evpn neighbor management code needs some values to use
* when programming neighbor changes. Offer some platform-neutral values
@@ -1078,6 +1090,26 @@ void dplane_set_in_queue_limit(uint32_t limit, bool set);
/* Retrieve the current queue depth of incoming, unprocessed updates */
uint32_t dplane_get_in_queue_len(void);
+void dplane_ctx_set_vlan_ifindex(struct zebra_dplane_ctx *ctx,
+ ifindex_t ifindex);
+ifindex_t dplane_ctx_get_vlan_ifindex(struct zebra_dplane_ctx *ctx);
+struct zebra_vxlan_vlan_array;
+
+/*
+ * In netlink_vlan_change(), the memory allocated for vlan_array is freed
+ * in two cases
+ * 1) Inline free in netlink_vlan_change() when there are no new
+ * vlans to process i.e. nothing is enqueued to main thread.
+ * 2) Dplane-ctx takes over the vlan memory which gets freed in
+ * rib_process_dplane_results() after handling the vlan install
+ *
+ * Note: MTYPE of interest for this purpose is MTYPE_VLAN_CHANGE_ARR
+ */
+void dplane_ctx_set_vxlan_vlan_array(struct zebra_dplane_ctx *ctx,
+ struct zebra_vxlan_vlan_array *vlan_array);
+const struct zebra_vxlan_vlan_array *
+dplane_ctx_get_vxlan_vlan_array(struct zebra_dplane_ctx *ctx);
+
/*
* Vty/cli apis
*/
diff --git a/zebra/zebra_l2.h b/zebra/zebra_l2.h
index 588917f4c0..ad5f5eeee0 100644
--- a/zebra/zebra_l2.h
+++ b/zebra/zebra_l2.h
@@ -146,6 +146,17 @@ union zebra_l2if_info {
struct zebra_l2info_gre gre;
};
+struct zebra_vxlan_vlan {
+ uint8_t state;
+ uint32_t vrange;
+ vlanid_t vid;
+};
+
+struct zebra_vxlan_vlan_array {
+ uint16_t count;
+ struct zebra_vxlan_vlan vlans[0];
+};
+
/* NOTE: These macros are to be invoked only in the "correct" context.
* IOW, the macro VNI_FROM_ZEBRA_IF() will assume the interface is
* of type ZEBRA_IF_VXLAN.
diff --git a/zebra/zebra_nb_state.c b/zebra/zebra_nb_state.c
index 63ac7877d0..6ed11f75f1 100644
--- a/zebra/zebra_nb_state.c
+++ b/zebra/zebra_nb_state.c
@@ -900,6 +900,7 @@ lib_vrf_zebra_ribs_rib_route_route_entry_nexthop_group_nexthop_bh_type_get_elem(
if (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)
return NULL;
+ (void)type_str; /* clang-SA */
switch (nexthop->bh_type) {
case BLACKHOLE_NULL:
type_str = "null";
diff --git a/zebra/zebra_netns_id.c b/zebra/zebra_netns_id.c
index 4cee3b89f1..3da79e249e 100644
--- a/zebra/zebra_netns_id.c
+++ b/zebra/zebra_netns_id.c
@@ -159,6 +159,7 @@ ns_id_t zebra_ns_id_get(const char *netnspath, int fd_param)
int fd = -1, sock, ret;
unsigned int seq;
ns_id_t return_nsid = NS_UNKNOWN;
+ int nl_errno;
/* netns path check */
if (!netnspath && fd_param == -1)
@@ -231,32 +232,31 @@ ns_id_t zebra_ns_id_get(const char *netnspath, int fd_param)
ret = -1;
if (err->error < 0)
- errno = -err->error;
+ nl_errno = -err->error;
else
- errno = err->error;
- if (errno == 0) {
+ nl_errno = err->error;
+ if (nl_errno == 0) {
/* request NEWNSID was successfull
* return EEXIST error to get GETNSID
*/
- errno = EEXIST;
+ nl_errno = EEXIST;
}
} else {
/* other errors ignored
* attempt to get nsid
*/
ret = -1;
- errno = EEXIST;
+ nl_errno = EEXIST;
}
}
- if (errno != EEXIST && ret != 0) {
- flog_err(EC_LIB_SOCKET,
- "netlink( %u) recvfrom() error 2 when reading: %s", fd,
- safe_strerror(errno));
+ if (ret != 0 && nl_errno != EEXIST) {
+ flog_err(EC_LIB_SOCKET, "netlink( %u) recvfrom() error 2 when reading: %s", fd,
+ safe_strerror(nl_errno));
close(sock);
if (netnspath)
close(fd);
- if (errno == ENOTSUP) {
+ if (nl_errno == ENOTSUP) {
zlog_debug("NEWNSID locally generated");
return zebra_ns_id_get_fallback(netnspath);
}
diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c
index 3ac4fdd737..52b94e0405 100644
--- a/zebra/zebra_netns_notify.c
+++ b/zebra/zebra_netns_notify.c
@@ -378,19 +378,28 @@ void zebra_ns_notify_parse(void)
{
struct dirent *dent;
DIR *srcdir = opendir(NS_RUN_DIR);
+ int srcdirfd;
if (srcdir == NULL) {
flog_err_sys(EC_LIB_SYSTEM_CALL,
"NS parsing init: failed to parse %s", NS_RUN_DIR);
return;
}
+
+ srcdirfd = dirfd(srcdir);
+ if (srcdirfd < 0) {
+ closedir(srcdir);
+ flog_err_sys(EC_LIB_SYSTEM_CALL, "NS parsing init: failed to parse %s", NS_RUN_DIR);
+ return;
+ }
+
while ((dent = readdir(srcdir)) != NULL) {
struct stat st;
if (strcmp(dent->d_name, ".") == 0
|| strcmp(dent->d_name, "..") == 0)
continue;
- if (fstatat(dirfd(srcdir), dent->d_name, &st, 0) < 0) {
+ if (fstatat(srcdirfd, dent->d_name, &st, 0) < 0) {
flog_err_sys(
EC_LIB_SYSTEM_CALL,
"NS parsing init: failed to parse entry %s",
diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c
index 803d8f0034..ffd749fcf1 100644
--- a/zebra/zebra_ns.c
+++ b/zebra/zebra_ns.c
@@ -175,6 +175,22 @@ int zebra_ns_early_shutdown(struct ns *ns,
return NS_WALK_CONTINUE;
}
+/* During zebra shutdown, do kernel cleanup
+ * netlink sockets, ..
+ */
+int zebra_ns_kernel_shutdown(struct ns *ns, void *param_in __attribute__((unused)),
+ void **param_out __attribute__((unused)))
+{
+ struct zebra_ns *zns = ns->info;
+
+ if (zns == NULL)
+ return NS_WALK_CONTINUE;
+
+ kernel_terminate(zns, true);
+
+ return NS_WALK_CONTINUE;
+}
+
/* During zebra shutdown, do final cleanup
* after all dataplane work is complete.
*/
@@ -185,9 +201,7 @@ int zebra_ns_final_shutdown(struct ns *ns,
struct zebra_ns *zns = ns->info;
if (zns == NULL)
- return 0;
-
- kernel_terminate(zns, true);
+ return NS_WALK_CONTINUE;
zebra_ns_delete(ns);
diff --git a/zebra/zebra_ns.h b/zebra/zebra_ns.h
index 8d988c3f82..d5fd5869bc 100644
--- a/zebra/zebra_ns.h
+++ b/zebra/zebra_ns.h
@@ -70,6 +70,8 @@ int zebra_ns_early_shutdown(struct ns *ns,
int zebra_ns_final_shutdown(struct ns *ns,
void *param_in __attribute__((unused)),
void **param_out __attribute__((unused)));
+int zebra_ns_kernel_shutdown(struct ns *ns, void *param_in __attribute__((unused)),
+ void **param_out __attribute__((unused)));
void zebra_ns_startup_continue(struct zebra_dplane_ctx *ctx);
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 8ebc193fba..72421dc8ee 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -795,13 +795,77 @@ void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq,
struct rnh *rnh;
/*
- * We are storing the rnh's associated withb
- * the tracked nexthop as a list of the rn's.
+ * We are storing the rnh's associated with
+ * the tracked nexthop as a list of the rnh's
+ * on the rn that we have matched to. As an
+ * example if you have these rnh's:
+ * rnh 1.1.1.1
+ * rnh 1.1.1.2
+ * rnh 1.1.3.4
+ * rnh 4.5.6.7
+ * Now imagine that you have in the tree these
+ * prefix's:
+ * 1.1.1.1/32
+ * 1.1.1.0/24
+ * 1.1.0.0/16
+ * 0.0.0.0/0
+ *
+ * The 1.1.1.1 rnh would be stored on 1.1.1.1/32
+ * The 1.1.1.2 rnh would be stored on 1.1.1.0/24
+ * The 1.1.3.4 rnh would be stored on the 1.1.0.0/16
+ * and finally the 4.5.6.7 would be stored on the 0.0.0.0/0
+ * prefix.
+ *
* Unresolved rnh's are placed at the top
* of the tree list.( 0.0.0.0/0 for v4 and 0::0/0 for v6 )
* As such for each rn we need to walk up the tree
* and see if any rnh's need to see if they
* would match a more specific route
+ *
+ * Now if a 1.1.1.2/32 prefix was added to the tree
+ * this function would start at this new node and
+ * see that the 1.1.1.2/32 node has no rnh's and
+ * there is nothing to do on this node currently,
+ * so the function would walk the parent pointers, until the
+ * 1.1.1.0/24 node is hit with the 1.1.1.2 rnh. This function
+ * would then call zebra_evaluate_rnh() which would then
+ * do a LPM and match on the 1.1.1.2/32 node. This function
+ * would then pull the 1.1.1.2 rnh off the 1.1.1.0/24 node
+ * and place it on the 1.1.1.1/32 node and notify the upper
+ * level protocols interested about the change( as necessary ).
+ * At this point in time a sequence number is added to note
+ * that the rnh has been moved.
+ * The function would also continue to walk up the tree
+ * looking at the list of rnh's and moving them around
+ * as necessary. Since in this example nothing else
+ * would change no further actions are made.
+ *
+ * Another case to consider is a node being deleted
+ * suppose the 1.1.1.2/32 route is being deleted.
+ * This function would start at the 1.1.1.1/32 node,
+ * perform a LPM and settle on the 1.1.1.0/24 node
+ * as where it belongs. The code would update appropriate
+ * interested parties and additionally also mark the sequence
+ * number and walk up the tree. Eventually it would get to
+ * the 1.1.1.0/24 node and since the seqno matches we would
+ * know that it is not necessary to reconsider this node
+ * as it was already moved to this spot.
+ *
+ * This all works because each node's parent pointer points
+ * to a node that has a prefix that contains this node. Eventually
+ * the parent traversal will hit the 0.0.0.0/0 node and we know
+ * we are done. We know this is pretty efficient because when
+ * a more specific is added as we walk the tree we can
+ * find the rnh's that matched to a less specific very easily
+ * and move them to a more specific node. Also vice-versa as a
+ * more specific node is removed.
+ *
+ * Long term the rnh code might be improved some as the rnh's
+ * are stored as a list. This might be transformed to a better
+ * data structure. This has not proven to be necessary yet as
+ * that we have not seen any particular case where a rn is
+ * storing more than a couple rnh's. If we find a case
+ * where this matters something might need to be done.
*/
while (rn) {
if (IS_ZEBRA_DEBUG_NHT_DETAILED)
@@ -5020,6 +5084,9 @@ static void rib_process_dplane_results(struct event *thread)
zebra_ns_startup_continue(ctx);
break;
+ case DPLANE_OP_VLAN_INSTALL:
+ zebra_vlan_dplane_result(ctx);
+ break;
} /* Dispatch by op code */
dplane_ctx_fini(&ctx);
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index 89317be74d..35486a4cd0 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -220,10 +220,9 @@ void zebra_free_rnh(struct rnh *rnh)
if (rern) {
rib_dest_t *dest;
- route_unlock_node(rern);
-
dest = rib_dest_from_rnode(rern);
rnh_list_del(&dest->nht, rnh);
+ route_unlock_node(rern);
}
}
free_state(rnh->vrf_id, rnh->state, rnh->node);
@@ -1141,7 +1140,7 @@ int zebra_send_rnh_update(struct rnh *rnh, struct zserv *client,
struct stream *s = NULL;
struct route_entry *re;
unsigned long nump;
- uint8_t num;
+ uint16_t num;
struct nexthop *nh;
struct route_node *rn;
int ret;
@@ -1212,7 +1211,7 @@ int zebra_send_rnh_update(struct rnh *rnh, struct zserv *client,
stream_putl(s, re->metric);
num = 0;
nump = stream_get_endp(s);
- stream_putc(s, 0);
+ stream_putw(s, 0);
nhg = rib_get_fib_nhg(re);
for (ALL_NEXTHOPS_PTR(nhg, nh))
@@ -1240,13 +1239,13 @@ int zebra_send_rnh_update(struct rnh *rnh, struct zserv *client,
}
}
- stream_putc_at(s, nump, num);
+ stream_putw_at(s, nump, num);
} else {
stream_putc(s, 0); // type
stream_putw(s, 0); // instance
stream_putc(s, 0); // distance
stream_putl(s, 0); // metric
- stream_putc(s, 0); // nexthops
+ stream_putw(s, 0); // nexthops
}
stream_putw_at(s, 0, stream_get_endp(s));
diff --git a/zebra/zebra_script.c b/zebra/zebra_script.c
index 6c34d12c64..a0d5e2054c 100644
--- a/zebra/zebra_script.c
+++ b/zebra/zebra_script.c
@@ -418,6 +418,7 @@ void lua_pushzebra_dplane_ctx(lua_State *L, const struct zebra_dplane_ctx *ctx)
case DPLANE_OP_SRV6_ENCAP_SRCADDR_SET:
case DPLANE_OP_NONE:
case DPLANE_OP_STARTUP_STAGE:
+ case DPLANE_OP_VLAN_INSTALL:
break;
} /* Dispatch by op code */
}
diff --git a/zebra/zebra_srte.c b/zebra/zebra_srte.c
index c0b83382c4..bb8d4b3b40 100644
--- a/zebra/zebra_srte.c
+++ b/zebra/zebra_srte.c
@@ -145,7 +145,7 @@ static int zebra_sr_policy_notify_update_client(struct zebra_sr_policy *policy,
stream_putc(s, nhlfe->distance);
stream_putl(s, 0); /* metric - not available */
nump = stream_get_endp(s);
- stream_putc(s, 0);
+ stream_putw(s, 0);
}
zapi_nexthop_from_nexthop(&znh, nhlfe->nexthop);
@@ -155,7 +155,7 @@ static int zebra_sr_policy_notify_update_client(struct zebra_sr_policy *policy,
num++;
}
- stream_putc_at(s, nump, num);
+ stream_putw_at(s, nump, num);
stream_putw_at(s, 0, stream_get_endp(s));
client->nh_last_upd_time = monotime(NULL);
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index f1ae42e320..0f72259951 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -6246,3 +6246,114 @@ extern void zebra_evpn_init(void)
{
hook_register(zserv_client_close, zebra_evpn_cfg_clean_up);
}
+
+static const char *port_state2str(uint8_t state)
+{
+ switch (state) {
+ case ZEBRA_DPLANE_BR_STATE_DISABLED:
+ return "DISABLED";
+ case ZEBRA_DPLANE_BR_STATE_LISTENING:
+ return "LISTENING";
+ case ZEBRA_DPLANE_BR_STATE_LEARNING:
+ return "LEARNING";
+ case ZEBRA_DPLANE_BR_STATE_FORWARDING:
+ return "FORWARDING";
+ case ZEBRA_DPLANE_BR_STATE_BLOCKING:
+ return "BLOCKING";
+ }
+
+ return "UNKNOWN";
+}
+
+static void vxlan_vni_state_change(struct zebra_if *zif, uint16_t id,
+ uint8_t state)
+{
+ struct zebra_vxlan_vni *vnip;
+
+ vnip = zebra_vxlan_if_vlanid_vni_find(zif, id);
+
+ if (!vnip) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("Cannot find VNI for VID (%u) IF %s for vlan state update",
+ id, zif->ifp->name);
+
+ return;
+ }
+
+ switch (state) {
+ case ZEBRA_DPLANE_BR_STATE_FORWARDING:
+ zebra_vxlan_if_vni_up(zif->ifp, vnip);
+ break;
+ case ZEBRA_DPLANE_BR_STATE_BLOCKING:
+ zebra_vxlan_if_vni_down(zif->ifp, vnip);
+ break;
+ case ZEBRA_DPLANE_BR_STATE_DISABLED:
+ case ZEBRA_DPLANE_BR_STATE_LISTENING:
+ case ZEBRA_DPLANE_BR_STATE_LEARNING:
+ default:
+ /* Not used for anything at the moment */
+ break;
+ }
+}
+
+static void vlan_id_range_state_change(struct interface *ifp, uint16_t id_start,
+ uint16_t id_end, uint8_t state)
+{
+ struct zebra_if *zif;
+
+ zif = (struct zebra_if *)ifp->info;
+
+ if (!zif)
+ return;
+
+ for (uint16_t i = id_start; i <= id_end; i++)
+ vxlan_vni_state_change(zif, i, state);
+}
+
+void zebra_vlan_dplane_result(struct zebra_dplane_ctx *ctx)
+{
+ int i;
+ struct interface *ifp = NULL;
+ ns_id_t ns_id = dplane_ctx_get_ns_id(ctx);
+ enum dplane_op_e op = dplane_ctx_get_op(ctx);
+ const struct zebra_vxlan_vlan_array *vlan_array =
+ dplane_ctx_get_vxlan_vlan_array(ctx);
+ ifindex_t ifindex = dplane_ctx_get_vlan_ifindex(ctx);
+
+ ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), ifindex);
+ if (!ifp) {
+ zlog_debug("Cannot find bridge-vlan IF (%u) for vlan update",
+ ifindex);
+ return;
+ }
+
+ if (!IS_ZEBRA_IF_VXLAN(ifp)) {
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("Ignoring non-vxlan IF (%s) for vlan update",
+ ifp->name);
+
+ return;
+ }
+
+ if (IS_ZEBRA_DEBUG_KERNEL || IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("Dequeuing in zebra main..%s IF %s ifindex %u NS %u",
+ dplane_op2str(op), ifp->name, ifindex, ns_id);
+
+ for (i = 0; i < vlan_array->count; i++) {
+ vlanid_t vid = vlan_array->vlans[i].vid;
+ uint8_t state = vlan_array->vlans[i].state;
+ uint32_t vrange = vlan_array->vlans[i].vrange;
+
+ if (IS_ZEBRA_DEBUG_KERNEL || IS_ZEBRA_DEBUG_VXLAN) {
+ if (vrange)
+ zlog_debug("VLANDB_ENTRY: VID (%u-%u) state=%s",
+ vid, vrange, port_state2str(state));
+ else
+ zlog_debug("VLANDB_ENTRY: VID (%u) state=%s",
+ vid, port_state2str(state));
+ }
+
+ vlan_id_range_state_change(ifp, vid, (vrange ? vrange : vid),
+ state);
+ }
+}
diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h
index eb02de6f7b..ef4c39c060 100644
--- a/zebra/zebra_vxlan.h
+++ b/zebra/zebra_vxlan.h
@@ -221,7 +221,7 @@ extern int zebra_vxlan_dp_network_mac_del(struct interface *ifp,
extern void zebra_vxlan_set_accept_bgp_seq(bool set);
extern bool zebra_vxlan_get_accept_bgp_seq(void);
-
+extern void zebra_vlan_dplane_result(struct zebra_dplane_ctx *ctx);
#ifdef __cplusplus
}
#endif