summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_flowspec.c2
-rw-r--r--bgpd/bgp_flowspec_vty.c10
-rw-r--r--bgpd/bgp_network.c3
-rw-r--r--bgpd/bgp_pbr.c13
-rw-r--r--bgpd/bgp_route.c26
-rw-r--r--bgpd/bgp_table.h4
-rw-r--r--lib/compiler.h9
-rw-r--r--lib/if.c3
-rw-r--r--lib/table.h8
-rw-r--r--lib/vrf.c6
-rw-r--r--lib/vrf.h2
-rw-r--r--pimd/pim_cmd.c4
-rw-r--r--pimd/pim_ifchannel.c11
-rw-r--r--pimd/pim_oil.c11
-rw-r--r--pimd/pim_upstream.c2
-rw-r--r--snapcraft/README.usage.md19
-rw-r--r--snapcraft/scripts/bgpd-service9
-rwxr-xr-xsnapcraft/scripts/set-options25
-rw-r--r--snapcraft/snapcraft.yaml.in25
-rw-r--r--staticd/static_vty.c24
-rw-r--r--staticd/static_zebra.c7
-rw-r--r--tests/bgpd/test_capability.c2
-rw-r--r--zebra/redistribute.c7
-rw-r--r--zebra/redistribute.h3
-rw-r--r--zebra/rib.h2
-rw-r--r--zebra/zebra_rib.c13
-rw-r--r--zebra/zebra_routemap.c136
27 files changed, 297 insertions, 89 deletions
diff --git a/bgpd/bgp_flowspec.c b/bgpd/bgp_flowspec.c
index 6695596c6f..e29508bf36 100644
--- a/bgpd/bgp_flowspec.c
+++ b/bgpd/bgp_flowspec.c
@@ -148,7 +148,7 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr,
if (BGP_DEBUG(flowspec, FLOWSPEC)) {
char return_string[BGP_FLOWSPEC_NLRI_STRING_MAX];
- char local_string[BGP_FLOWSPEC_NLRI_STRING_MAX * 2];
+ char local_string[BGP_FLOWSPEC_NLRI_STRING_MAX*2+16];
char ec_string[BGP_FLOWSPEC_NLRI_STRING_MAX];
char *s = NULL;
diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c
index f8c0613208..31d2c540fa 100644
--- a/bgpd/bgp_flowspec_vty.c
+++ b/bgpd/bgp_flowspec_vty.c
@@ -335,7 +335,7 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
struct listnode *node;
struct bgp_pbr_match_entry *bpme;
struct bgp_pbr_match *bpm;
- int unit = 0;
+ bool list_began = false;
struct list *list_bpm;
list_bpm = list_new();
@@ -347,14 +347,14 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p,
if (listnode_lookup(list_bpm, bpm))
continue;
listnode_add(list_bpm, bpm);
- if (unit == 0)
+ if (!list_began) {
vty_out(vty, " (");
- else
+ list_began = true;
+ } else
vty_out(vty, ", ");
vty_out(vty, "%s", bpm->ipset_name);
- unit++;
}
- if (unit)
+ if (list_began)
vty_out(vty, ")");
vty_out(vty, "\n");
list_delete_and_null(&list_bpm);
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index 0664fdfd1c..22d5d35c82 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -672,7 +672,8 @@ static int bgp_listener(int sock, struct sockaddr *sa, socklen_t salen,
listener->fd = sock;
/* this socket needs a change of ns. record bgp back pointer */
- if (bgp->vrf_id != VRF_DEFAULT && vrf_is_mapped_on_netns(bgp->vrf_id))
+ if (bgp->vrf_id != VRF_DEFAULT && vrf_is_mapped_on_netns(
+ vrf_lookup_by_id(bgp->vrf_id)))
listener->bgp = bgp;
memcpy(&listener->su, sa, salen);
diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c
index 129c143a64..b182fde1e2 100644
--- a/bgpd/bgp_pbr.c
+++ b/bgpd/bgp_pbr.c
@@ -1680,7 +1680,7 @@ static void bgp_pbr_dump_entry(struct bgp_pbr_filter *bpf, bool add)
? "!" : "",
bpf->dscp->val);
}
- zlog_info("BGP: %s FS PBR from %s to %s, %s %s",
+ zlog_debug("BGP: %s FS PBR from %s to %s, %s %s",
add ? "adding" : "removing",
bpf->src == NULL ? "<all>" :
prefix2str(bpf->src, bufsrc, sizeof(bufsrc)),
@@ -1807,7 +1807,7 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
bgp_pbr_match_alloc_intern);
/* new, then self allocate ipset_name and unique */
- if (bpm && bpm->unique == 0) {
+ if (bpm->unique == 0) {
bpm->unique = ++bgp_pbr_match_counter_unique;
/* 0 value is forbidden */
sprintf(bpm->ipset_name, "match%p", bpm);
@@ -1838,10 +1838,9 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
temp2.src_port_max = src_port ? src_port->max_port : 0;
temp2.dst_port_max = dst_port ? dst_port->max_port : 0;
temp2.proto = bpf->protocol;
- if (bpm)
- bpme = hash_get(bpm->entry_hash, &temp2,
- bgp_pbr_match_entry_alloc_intern);
- if (bpme && bpme->unique == 0) {
+ bpme = hash_get(bpm->entry_hash, &temp2,
+ bgp_pbr_match_entry_alloc_intern);
+ if (bpme->unique == 0) {
bpme->unique = ++bgp_pbr_match_entry_counter_unique;
/* 0 value is forbidden */
bpme->backpointer = bpm;
@@ -1853,7 +1852,7 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
bpme_found = true;
/* already installed */
- if (bpme_found && bpme) {
+ if (bpme_found) {
struct bgp_info_extra *extra = bgp_info_extra_get(binfo);
if (extra && extra->bgp_fs_pbr &&
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 041049d05b..e38257d564 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -188,8 +188,24 @@ static void bgp_info_extra_free(struct bgp_info_extra **extra)
if (e->parent) {
struct bgp_info *bi = (struct bgp_info *)e->parent;
- if (bi->net)
- bi->net = bgp_unlock_node((struct bgp_node *)bi->net);
+ if (bi->net) {
+ /* FIXME: since multiple e may have the same e->parent
+ * and e->parent->net is holding a refcount for each
+ * of them, we need to do some fudging here.
+ *
+ * WARNING: if bi->net->lock drops to 0, bi may be
+ * freed as well (because bi->net was holding the
+ * last reference to bi) => write after free!
+ */
+ unsigned refcount;
+
+ bi = bgp_info_lock(bi);
+ refcount = bi->net->lock - 1;
+ bgp_unlock_node((struct bgp_node *)bi->net);
+ if (!refcount)
+ bi->net = NULL;
+ bgp_info_unlock(bi);
+ }
bgp_info_unlock(e->parent);
e->parent = NULL;
}
@@ -198,8 +214,7 @@ static void bgp_info_extra_free(struct bgp_info_extra **extra)
bgp_unlock(e->bgp_orig);
if ((*extra)->bgp_fs_pbr)
- list_delete_all_node((*extra)->bgp_fs_pbr);
- (*extra)->bgp_fs_pbr = NULL;
+ list_delete_and_null(&((*extra)->bgp_fs_pbr));
XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
*extra = NULL;
@@ -8187,7 +8202,6 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
vty_out(vty, " \"routeDistinguishers\" : {");
++*json_header_depth;
}
- json_paths = json_object_new_object();
}
if (use_json && rd) {
@@ -8414,8 +8428,6 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
*total_cum = total_count;
}
if (use_json) {
- if (json_paths)
- json_object_free(json_paths);
if (rd) {
vty_out(vty, " }%s ", (is_last ? "" : ","));
}
diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h
index f7eac09546..60c2cbd4a4 100644
--- a/bgpd/bgp_table.h
+++ b/bgpd/bgp_table.h
@@ -128,9 +128,9 @@ static inline struct bgp_node *bgp_node_parent_nolock(struct bgp_node *node)
/*
* bgp_unlock_node
*/
-static inline struct bgp_node *bgp_unlock_node(struct bgp_node *node)
+static inline void bgp_unlock_node(struct bgp_node *node)
{
- return (struct bgp_node *)route_unlock_node(bgp_node_to_rnode(node));
+ route_unlock_node(bgp_node_to_rnode(node));
}
/*
diff --git a/lib/compiler.h b/lib/compiler.h
index b19c33f65e..24b8fafd10 100644
--- a/lib/compiler.h
+++ b/lib/compiler.h
@@ -24,6 +24,9 @@
#if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 5)
# define _RET_NONNULL , returns_nonnull
#endif
+#if __has_attribute(fallthrough)
+# define _FALLTHROUGH __attribute__((fallthrough));
+#endif
# define _CONSTRUCTOR(x) constructor(x)
#elif defined(__GNUC__)
#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
@@ -34,6 +37,9 @@
# define _DESTRUCTOR(x) destructor(x)
# define _ALLOC_SIZE(x) alloc_size(x)
#endif
+#if __GNUC__ >= 7
+# define _FALLTHROUGH __attribute__((fallthrough));
+#endif
#endif
#ifdef __sun
@@ -55,6 +61,9 @@
#ifndef _ALLOC_SIZE
# define _ALLOC_SIZE(x)
#endif
+#ifndef _FALLTHROUGH
+#define _FALLTHROUGH
+#endif
/*
* for warnings on macros, put in the macro content like this:
diff --git a/lib/if.c b/lib/if.c
index 6023624dc1..11c4f1b5dc 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -393,7 +393,8 @@ struct interface *if_get_by_name(const char *name, vrf_id_t vrf_id, int vty)
* this should not be considered as an update
* then create the new interface
*/
- if (ifp->vrf_id != vrf_id && vrf_is_mapped_on_netns(vrf_id))
+ if (ifp->vrf_id != vrf_id && vrf_is_mapped_on_netns(
+ vrf_lookup_by_id(vrf_id)))
return if_create(name, vrf_id);
/* If it came from the kernel
* or by way of zclient, believe it and update
diff --git a/lib/table.h b/lib/table.h
index ac7df3e695..8304abe59b 100644
--- a/lib/table.h
+++ b/lib/table.h
@@ -235,17 +235,13 @@ static inline struct route_node *route_lock_node(struct route_node *node)
}
/* Unlock node. */
-static inline struct route_node *route_unlock_node(struct route_node *node)
+static inline void route_unlock_node(struct route_node *node)
{
assert(node->lock > 0);
(*(unsigned *)&node->lock)--;
- if (node->lock == 0) {
+ if (node->lock == 0)
route_node_delete(node);
- return NULL;
- }
-
- return node;
}
/*
diff --git a/lib/vrf.c b/lib/vrf.c
index 36111dfeae..3c7342bb98 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -682,10 +682,8 @@ int vrf_netns_handler_create(struct vty *vty, struct vrf *vrf, char *pathname,
return CMD_SUCCESS;
}
-int vrf_is_mapped_on_netns(vrf_id_t vrf_id)
+int vrf_is_mapped_on_netns(struct vrf *vrf)
{
- struct vrf *vrf = vrf_lookup_by_id(vrf_id);
-
if (!vrf || vrf->data.l.netns_name[0] == '\0')
return 0;
if (vrf->vrf_id == VRF_DEFAULT)
@@ -887,7 +885,7 @@ int vrf_bind(vrf_id_t vrf_id, int fd, char *name)
if (fd < 0 || name == NULL)
return fd;
- if (vrf_is_mapped_on_netns(vrf_id))
+ if (vrf_is_mapped_on_netns(vrf_lookup_by_id(vrf_id)))
return fd;
#ifdef SO_BINDTODEVICE
ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, name, strlen(name)+1);
diff --git a/lib/vrf.h b/lib/vrf.h
index 0f4f36be50..56ba101ff0 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -237,7 +237,7 @@ extern vrf_id_t vrf_get_default_id(void);
#define VRF_DEFAULT vrf_get_default_id()
/* VRF is mapped on netns or not ? */
-int vrf_is_mapped_on_netns(vrf_id_t vrf_id);
+int vrf_is_mapped_on_netns(struct vrf *vrf);
/* VRF switch from NETNS */
extern int vrf_switch_to_netns(vrf_id_t vrf_id);
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 7c45ce261a..611d8d3681 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -323,8 +323,8 @@ static void pim_show_assert_winner_metric_helper(struct vty *vty,
char addr_str[INET_ADDRSTRLEN];
struct pim_assert_metric *am;
struct in_addr ifaddr;
- char pref_str[5];
- char metr_str[7];
+ char pref_str[16];
+ char metr_str[16];
ifaddr = pim_ifp->primary_address;
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index 92a78c4bb4..3137345037 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -174,7 +174,16 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
ifchannel list is empty before deleting upstream_del
ref count will take care of it.
*/
- pim_upstream_del(pim_ifp->pim, ch->upstream, __PRETTY_FUNCTION__);
+ if (ch->upstream->ref_count > 0)
+ pim_upstream_del(pim_ifp->pim, ch->upstream,
+ __PRETTY_FUNCTION__);
+
+ else
+ zlog_warn("%s: Avoiding deletion of upstream with ref_count %d "
+ "from ifchannel(%s): %s", __PRETTY_FUNCTION__,
+ ch->upstream->ref_count, ch->interface->name,
+ ch->sg_str);
+
ch->upstream = NULL;
THREAD_OFF(ch->t_ifjoin_expiry_timer);
diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c
index f0f336fb73..a0debc0c78 100644
--- a/pimd/pim_oil.c
+++ b/pimd/pim_oil.c
@@ -37,19 +37,20 @@
char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size)
{
+ char *out;
struct prefix_sg sg;
int i;
sg.src = c_oil->oil.mfcc_origin;
sg.grp = c_oil->oil.mfcc_mcastgrp;
- sprintf(buf, "%s IIF: %d, OIFS: ", pim_str_sg_dump(&sg),
- c_oil->oil.mfcc_parent);
+ snprintf(buf, size, "%s IIF: %d, OIFS: ", pim_str_sg_dump(&sg),
+ c_oil->oil.mfcc_parent);
+ out = buf + strlen(buf);
for (i = 0; i < MAXVIFS; i++) {
if (c_oil->oil.mfcc_ttls[i] != 0) {
- char buf1[10];
- sprintf(buf1, "%d ", i);
- strcat(buf, buf1);
+ snprintf(out, buf + size - out, "%d ", i);
+ out += strlen(out);
}
}
diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c
index db89125a98..15cbf6fbc3 100644
--- a/pimd/pim_upstream.c
+++ b/pimd/pim_upstream.c
@@ -167,6 +167,8 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
up->ref_count, up->flags,
up->channel_oil->oil_ref_count);
+ assert(up->ref_count > 0);
+
--up->ref_count;
if (up->ref_count >= 1)
diff --git a/snapcraft/README.usage.md b/snapcraft/README.usage.md
index 50711b13b7..a7b51a5656 100644
--- a/snapcraft/README.usage.md
+++ b/snapcraft/README.usage.md
@@ -31,7 +31,7 @@ Commands defined by this snap
- `frr.readme`:
Returns this document `cat README_usage.md`
- `frr.set`:
- Allows to enable `FPM` module. See FPM section below
+ Allows to enable `FPM` and/or disable RPKIi module. See Module section below
and for debugging defined at this time (May get removed later - do not
depend on them). These are mainly intended to debug the Snap
@@ -100,13 +100,13 @@ are named `eth0`, `eth1` and `eth2`, then the additional lines in
These settings require either a reboot or a manual configuration with
`sysctl` as well.
-FPM Module
+Modules
----------
-The `frr.set` allows to turn FPM module on or off.
+The `frr.set` allows to turn FPM module ond the RPKI module on or off.
frr.set fpm {disable|protobuf|netlink}
- Disables FPM or enables FPM with selected mode
+ Disables FPM or enables FPM with selected mode (default: disabled)
By default, the FPM module is disabled, but installed with netlink and
protobuf support. To enable the FPM module, use the `frr.set fpm protobuf`
@@ -114,6 +114,17 @@ or `frr.set fpm netlink` command. The command will only enable the mode
for the next restart of zebra. Please reboot or restart zebra after
changing the mode to become effective.
+ frr.set rpki {enable|disable}
+
+ Disables or enables BGP RPKI (default: enabled)
+
+By default, the RPKI module is enabled. To disable the RPKI module
+use the `frr.set rpki disable` command. The command will only enable
+the module after the next restart of the bgp daemon. Please reboot or
+restart bgpd after changing the mode to become effective.
+(Normally, there is no need to disable the module as it has no effect
+if there are no RPKI configurations in BGP)
+
FAQ
---
- frr.vtysh displays `--MORE--` on long output. How to suppress this?
diff --git a/snapcraft/scripts/bgpd-service b/snapcraft/scripts/bgpd-service
index 4072031eda..6c3a6f5959 100644
--- a/snapcraft/scripts/bgpd-service
+++ b/snapcraft/scripts/bgpd-service
@@ -5,9 +5,16 @@ set -e -x
if ! [ -e $SNAP_DATA/bgpd.conf ]; then
cp $SNAP/etc/frr/bgpd.conf.default $SNAP_DATA/bgpd.conf
fi
+# If no RPKI option is specified, then we create a default
+# with RPKI enabled
+if ! [ -e $SNAP_DATA/rpki.conf ]; then
+ echo "-M rpki" > $SNAP_DATA/rpki.conf
+fi
+EXTRA_OPTIONS="`cat $SNAP_DATA/rpki.conf`"
exec $SNAP/sbin/bgpd \
-f $SNAP_DATA/bgpd.conf \
--pid_file $SNAP_DATA/bgpd.pid \
--socket $SNAP_DATA/zsock \
- --vty_socket $SNAP_DATA
+ --vty_socket $SNAP_DATA \
+ --moduledir $SNAP/lib/frr/modules $EXTRA_OPTIONS
diff --git a/snapcraft/scripts/set-options b/snapcraft/scripts/set-options
index e76e321ef8..0637d2ce5d 100755
--- a/snapcraft/scripts/set-options
+++ b/snapcraft/scripts/set-options
@@ -28,11 +28,34 @@ case $1 in
;;
esac
;;
+ rpki)
+ case $2 in
+ disable)
+ echo "" > $SNAP_DATA/rpki.conf
+ echo "RPKI module disabled. Please restart FRR"
+ ;;
+ enable)
+ echo "-M rpki" > $SNAP_DATA/rpki.conf
+ echo "RPKI module enabled. Please restart FRR"
+ ;;
+ *)
+ echo "Usage:"
+ echo " ${SNAP_NAME}.set rpki {disable|enable}"
+ echo ""
+ echo " Disables BGP RPKI module or enables it (default: enabled)"
+ echo " Mode will be saved for next restart of bgpd, but bgpd"
+ echo " is not automatically restarted"
+ exit 1
+ ;;
+ esac
+ ;;
*)
echo "Usage:"
echo " ${SNAP_NAME}.set fpm {disable|protobuf|netlink}"
+ echo " ${SNAP_NAME}.set rpki {disable|enable}"
echo ""
- echo " Disables FPM or enables FPM with selected mode"
+ echo " fpm: Disables FPM or enables FPM with selected mode"
+ echo " rpki: Disables BGP RPKI or enables it (default: enabled)"
exit 1
;;
esac
diff --git a/snapcraft/snapcraft.yaml.in b/snapcraft/snapcraft.yaml.in
index 563a05c5a7..b70d6efee2 100644
--- a/snapcraft/snapcraft.yaml.in
+++ b/snapcraft/snapcraft.yaml.in
@@ -136,7 +136,7 @@ apps:
- network-bind
- network-control
bgpd-debug:
- command: sbin/bgpd -f $SNAP_DATA/bgpd.conf --pid_file $SNAP_DATA/bgpd.pid --socket $SNAP_DATA/zsock --vty_socket $SNAP_DATA
+ command: sbin/bgpd -f $SNAP_DATA/bgpd.conf --pid_file $SNAP_DATA/bgpd.pid --socket $SNAP_DATA/zsock --vty_socket $SNAP_DATA --moduledir $SNAP/lib/frr/modules `cat $SNAP_DATA/rpki.conf 2> /dev/null`
plugs:
- network
- network-bind
@@ -221,8 +221,27 @@ apps:
- network-control
parts:
+ rtrlib:
+ build-packages:
+ - cmake
+ - make
+ - gcc
+ - libssh-dev
+ stage-packages:
+ - libssh-4
+ prime:
+ - lib/x86_64-linux-gnu/librtr.so*
+ - usr/lib/x86_64-linux-gnu/libssh.so*
+ source: https://github.com/rtrlib/rtrlib.git
+ source-type: git
+ source-tag: v0.5.0
+ plugin: cmake
+ configflags:
+ - -DCMAKE_BUILD_TYPE=Release
frr:
- build-packages:
+ after: [rtrlib]
+ build-packages:
+ - gcc
- autoconf
- automake
- libtool
@@ -247,6 +266,7 @@ parts:
- flex
- python3-dev
- protobuf-c-compiler
+ - python3-sphinx
stage-packages:
- coreutils
- iproute2
@@ -276,6 +296,7 @@ parts:
- --enable-ldpd
- --enable-fpm
- --enable-protobuf
+ - --enable-rpki
- --enable-configfile-mask=0640
- --enable-logfile-mask=0640
- --localstatedir=/var/run
diff --git a/staticd/static_vty.c b/staticd/static_vty.c
index 98153f7149..771d8d1de3 100644
--- a/staticd/static_vty.c
+++ b/staticd/static_vty.c
@@ -766,7 +766,7 @@ DEFPY(ip_route_blackhole,
"Table to configure\n"
"The table number to configure\n")
{
- if (table_str && !vrf_is_backend_netns()) {
+ if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -805,7 +805,7 @@ DEFPY(ip_route_blackhole_vrf,
VTY_DECLVAR_CONTEXT(vrf, vrf);
struct static_vrf *svrf = vrf->info;
- if (table_str && !vrf_is_backend_netns()) {
+ if (table_str && !vrf_is_mapped_on_netns(vrf)) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -868,7 +868,7 @@ DEFPY(ip_route_address_interface,
return CMD_WARNING_CONFIG_FAILED;
}
- if (table_str && !vrf_is_backend_netns()) {
+ if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -924,7 +924,7 @@ DEFPY(ip_route_address_interface_vrf,
struct static_vrf *svrf = vrf->info;
struct static_vrf *nh_svrf;
- if (table_str && !vrf_is_backend_netns()) {
+ if (table_str && !vrf_is_mapped_on_netns(vrf)) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -984,7 +984,7 @@ DEFPY(ip_route,
struct static_vrf *nh_svrf;
const char *flag = NULL;
- if (table_str && !vrf_is_backend_netns()) {
+ if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -1049,7 +1049,7 @@ DEFPY(ip_route_vrf,
struct static_vrf *nh_svrf;
const char *flag = NULL;
- if (table_str && !vrf_is_backend_netns()) {
+ if (table_str && !vrf_is_mapped_on_netns(vrf)) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -1104,7 +1104,7 @@ DEFPY(ipv6_route_blackhole,
"Table to configure\n"
"The table number to configure\n")
{
- if (table_str && !vrf_is_backend_netns()) {
+ if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -1144,7 +1144,7 @@ DEFPY(ipv6_route_blackhole_vrf,
VTY_DECLVAR_CONTEXT(vrf, vrf);
struct static_vrf *svrf = vrf->info;
- if (table_str && !vrf_is_backend_netns()) {
+ if (table_str && !vrf_is_mapped_on_netns(vrf)) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -1195,7 +1195,7 @@ DEFPY(ipv6_route_address_interface,
struct static_vrf *svrf;
struct static_vrf *nh_svrf;
- if (table_str && !vrf_is_backend_netns()) {
+ if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -1255,7 +1255,7 @@ DEFPY(ipv6_route_address_interface_vrf,
struct static_vrf *svrf = vrf->info;
struct static_vrf *nh_svrf;
- if (table_str && !vrf_is_backend_netns()) {
+ if (table_str && !vrf_is_mapped_on_netns(vrf)) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -1309,7 +1309,7 @@ DEFPY(ipv6_route,
struct static_vrf *svrf;
struct static_vrf *nh_svrf;
- if (table_str && !vrf_is_backend_netns()) {
+ if (table_str && vrf && !vrf_is_mapped_on_netns(vrf_lookup_by_name(vrf))) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -1368,7 +1368,7 @@ DEFPY(ipv6_route_vrf,
struct static_vrf *svrf = vrf->info;
struct static_vrf *nh_svrf;
- if (table_str && !vrf_is_backend_netns()) {
+ if (table_str && !vrf_is_mapped_on_netns(vrf)) {
vty_out(vty,
"%% table param only available when running on netns-based vrfs\n");
return CMD_WARNING_CONFIG_FAILED;
diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c
index f3175e91fa..56ba70eaf8 100644
--- a/staticd/static_zebra.c
+++ b/staticd/static_zebra.c
@@ -273,9 +273,10 @@ extern void static_zebra_route_add(struct route_node *rn,
SET_FLAG(api.message, ZAPI_MESSAGE_TAG);
api.tag = si_changed->tag;
}
- api.tableid = si_changed->table_id;
-
- zlog_debug("Distance sent down: %d %d", si_changed->distance, install);
+ if (si_changed->table_id != 0) {
+ SET_FLAG(api.message, ZAPI_MESSAGE_TABLEID);
+ api.tableid = si_changed->table_id;
+ }
for (/*loaded above*/; si; si = si->next) {
api_nh = &api.nexthops[nh_num];
if (si->nh_vrf_id == VRF_UNKNOWN)
diff --git a/tests/bgpd/test_capability.c b/tests/bgpd/test_capability.c
index 4612bdc26b..fef7d39ff5 100644
--- a/tests/bgpd/test_capability.c
+++ b/tests/bgpd/test_capability.c
@@ -821,7 +821,7 @@ static void parse_test(struct peer *peer, struct test_segment *t, int type)
switch (type) {
case CAPABILITY:
len += 2; /* to cover the OPT-Param header */
- __attribute__ ((fallthrough));
+ _FALLTHROUGH
case OPT_PARAM:
printf("len: %u\n", len);
/* peek_for_as4 wants getp at capibility*/
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index e3101fbe72..640d58e17e 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -715,7 +715,7 @@ int zebra_import_table_config(struct vty *vty)
return write;
}
-void zebra_import_table_rm_update()
+void zebra_import_table_rm_update(const char *rmap)
{
afi_t afi;
int i;
@@ -730,9 +730,8 @@ void zebra_import_table_rm_update()
continue;
rmap_name = zebra_get_import_table_route_map(afi, i);
- if (!rmap_name)
- return;
-
+ if ((!rmap_name) || (strcmp(rmap_name, rmap) != 0))
+ continue;
table = zebra_vrf_other_route_table(afi, i,
VRF_DEFAULT);
for (rn = route_top(table); rn; rn = route_next(rn)) {
diff --git a/zebra/redistribute.h b/zebra/redistribute.h
index a0fbd13cf9..f67480da9c 100644
--- a/zebra/redistribute.h
+++ b/zebra/redistribute.h
@@ -71,6 +71,5 @@ extern int is_zebra_import_table_enabled(afi_t, uint32_t table_id);
extern int zebra_import_table_config(struct vty *);
-extern void zebra_import_table_rm_update(void);
-
+extern void zebra_import_table_rm_update(const char *rmap);
#endif /* _ZEBRA_REDISTRIBUTE_H */
diff --git a/zebra/rib.h b/zebra/rib.h
index a37b2bf221..f821c6edb4 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -325,6 +325,8 @@ extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p,
vrf_id_t vrf_id);
extern void rib_update(vrf_id_t vrf_id, rib_update_event_t event);
+extern void rib_update_table(struct route_table *table,
+ rib_update_event_t event);
extern void rib_sweep_route(void);
extern void rib_sweep_table(struct route_table *table);
extern void rib_close_table(struct route_table *table);
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index b477cd4706..99b83d5cd9 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -2651,8 +2651,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
}
/* Schedule routes of a particular table (address-family) based on event. */
-static void rib_update_table(struct route_table *table,
- rib_update_event_t event)
+void rib_update_table(struct route_table *table, rib_update_event_t event)
{
struct route_node *rn;
struct route_entry *re, *next;
@@ -2732,12 +2731,18 @@ void rib_update(vrf_id_t vrf_id, rib_update_event_t event)
/* Process routes of interested address-families. */
table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, vrf_id);
- if (table)
+ if (table) {
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("%s : AFI_IP event %d", __func__, event);
rib_update_table(table, event);
+ }
table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, vrf_id);
- if (table)
+ if (table) {
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("%s : AFI_IP6 event %d", __func__, event);
rib_update_table(table, event);
+ }
}
/* Delete self installed routes after zebra is relaunched. */
diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c
index fc17ee3491..7a6bc6684d 100644
--- a/zebra/zebra_routemap.c
+++ b/zebra/zebra_routemap.c
@@ -1033,13 +1033,13 @@ static struct route_map_rule_cmd route_match_ip_address_cmd = {
/* `match ip address prefix-list PREFIX_LIST' */
static route_map_result_t
-route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
- route_map_object_t type, void *object)
+route_match_address_prefix_list(void *rule, const struct prefix *prefix,
+ route_map_object_t type, void *object, afi_t afi)
{
struct prefix_list *plist;
if (type == RMAP_ZEBRA) {
- plist = prefix_list_lookup(AFI_IP, (char *)rule);
+ plist = prefix_list_lookup(afi, (char *)rule);
if (plist == NULL)
return RMAP_NOMATCH;
@@ -1050,21 +1050,41 @@ route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
return RMAP_NOMATCH;
}
-static void *route_match_ip_address_prefix_list_compile(const char *arg)
+static route_map_result_t
+route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ return (route_match_address_prefix_list(rule, prefix, type, object,
+ AFI_IP));
+}
+
+static void *route_match_address_prefix_list_compile(const char *arg)
{
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
}
-static void route_match_ip_address_prefix_list_free(void *rule)
+static void route_match_address_prefix_list_free(void *rule)
{
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
}
static struct route_map_rule_cmd route_match_ip_address_prefix_list_cmd = {
"ip address prefix-list", route_match_ip_address_prefix_list,
- route_match_ip_address_prefix_list_compile,
- route_match_ip_address_prefix_list_free};
+ route_match_address_prefix_list_compile,
+ route_match_address_prefix_list_free};
+static route_map_result_t
+route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
+ route_map_object_t type, void *object)
+{
+ return (route_match_address_prefix_list(rule, prefix, type, object,
+ AFI_IP6));
+}
+
+static struct route_map_rule_cmd route_match_ipv6_address_prefix_list_cmd = {
+ "ipv6 address prefix-list", route_match_ipv6_address_prefix_list,
+ route_match_address_prefix_list_compile,
+ route_match_address_prefix_list_free};
/* `match ip address prefix-len PREFIXLEN' */
@@ -1281,11 +1301,101 @@ static struct route_map_rule_cmd route_set_src_cmd = {
"src", route_set_src, route_set_src_compile, route_set_src_free,
};
+/* The function checks if the changed routemap specified by parameter rmap
+ * matches the configured protocol routemaps in proto_rm table. If there is
+ * a match then rib_update_table() to process the routes.
+ */
+static void zebra_rib_table_rm_update(const char *rmap)
+{
+ int i = 0;
+ struct route_table *table;
+ char *rmap_name;
+ char afi_ip = 0;
+ char afi_ipv6 = 0;
+
+ for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
+ /* Check for ip routemap table */
+ rmap_name = proto_rm[AFI_IP][i];
+ if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("%s : AFI_IP rmap %s, route type %s",
+ __func__, rmap, zebra_route_string(i));
+ /* There is single rib table for all protocols */
+ if (afi_ip == 0) {
+ table = zebra_vrf_table(AFI_IP, SAFI_UNICAST,
+ VRF_DEFAULT);
+ if (table) {
+ afi_ip = 1;
+ rib_update_table(table,
+ RIB_UPDATE_RMAP_CHANGE);
+ }
+ }
+ }
+
+ /* Check for ipv6 routemap table */
+ rmap_name = proto_rm[AFI_IP6][i];
+ if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("%s : AFI_IP6 rmap %s,route type %s",
+ __func__, rmap, zebra_route_string(i));
+ if (afi_ipv6 == 0) {
+ table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST,
+ VRF_DEFAULT);
+ if (table) {
+ afi_ipv6 = 1;
+ rib_update_table(table,
+ RIB_UPDATE_RMAP_CHANGE);
+ }
+ }
+ }
+ }
+}
+
+/* The function checks if the changed routemap specified by parameter rmap
+ * matches the configured protocol routemaps in nht_rm table. If there is
+ * a match then zebra_evaluate_rnh() to process the nexthops.
+ */
+static void zebra_nht_rm_update(const char *rmap)
+{
+ int i = 0;
+ char *rmap_name;
+ char afi_ip = 0;
+ char afi_ipv6 = 0;
+
+ for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
+ rmap_name = nht_rm[AFI_IP][i];
+ if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("%s : AFI_IP rmap %s route type %s",
+ __func__, rmap, zebra_route_string(i));
+ if (afi_ip == 0) {
+ afi_ip = 1;
+ zebra_evaluate_rnh(0, AF_INET, 1,
+ RNH_NEXTHOP_TYPE, NULL);
+ }
+ }
+ rmap_name = nht_rm[AFI_IP6][i];
+ if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
+ if (IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("%s : AFI_IP6 rmap %s route type %s",
+ __func__, rmap, zebra_route_string(i));
+ if (afi_ipv6 == 0) {
+ afi_ipv6 = 1;
+ zebra_evaluate_rnh(0, AF_INET6, 1,
+ RNH_NEXTHOP_TYPE, NULL);
+ }
+ }
+ }
+}
+
static void zebra_route_map_process_update_cb(char *rmap_name)
{
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("Event handler for route-map: %s",
rmap_name);
+ zebra_import_table_rm_update(rmap_name);
+ zebra_rib_table_rm_update(rmap_name);
+ zebra_nht_rm_update(rmap_name);
}
static int zebra_route_map_update_timer(struct thread *thread)
@@ -1307,11 +1417,6 @@ static int zebra_route_map_update_timer(struct thread *thread)
* 1) VRF Aware <sigh>
* 2) Route-map aware
*/
- zebra_import_table_rm_update();
- rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE);
- zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL);
- zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL);
-
return (0);
}
@@ -1555,12 +1660,19 @@ void zebra_route_map_init()
route_map_match_tag_hook(generic_match_add);
route_map_no_match_tag_hook(generic_match_delete);
+ route_map_match_ipv6_address_hook(generic_match_add);
+ route_map_no_match_ipv6_address_hook(generic_match_delete);
+
+ route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
+ route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
+
route_map_install_match(&route_match_tag_cmd);
route_map_install_match(&route_match_interface_cmd);
route_map_install_match(&route_match_ip_next_hop_cmd);
route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
route_map_install_match(&route_match_ip_address_cmd);
route_map_install_match(&route_match_ip_address_prefix_list_cmd);
+ route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
route_map_install_match(&route_match_ip_address_prefix_len_cmd);
route_map_install_match(&route_match_ipv6_address_prefix_len_cmd);
route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd);