diff options
| -rw-r--r-- | bgpd/bgp_flowspec.c | 2 | ||||
| -rw-r--r-- | bgpd/bgp_flowspec_vty.c | 10 | ||||
| -rw-r--r-- | bgpd/bgp_network.c | 3 | ||||
| -rw-r--r-- | bgpd/bgp_pbr.c | 13 | ||||
| -rw-r--r-- | bgpd/bgp_route.c | 26 | ||||
| -rw-r--r-- | bgpd/bgp_table.h | 4 | ||||
| -rw-r--r-- | lib/compiler.h | 9 | ||||
| -rw-r--r-- | lib/if.c | 3 | ||||
| -rw-r--r-- | lib/table.h | 8 | ||||
| -rw-r--r-- | lib/vrf.c | 6 | ||||
| -rw-r--r-- | lib/vrf.h | 2 | ||||
| -rw-r--r-- | pimd/pim_cmd.c | 4 | ||||
| -rw-r--r-- | pimd/pim_ifchannel.c | 11 | ||||
| -rw-r--r-- | pimd/pim_oil.c | 11 | ||||
| -rw-r--r-- | pimd/pim_upstream.c | 2 | ||||
| -rw-r--r-- | snapcraft/README.usage.md | 19 | ||||
| -rw-r--r-- | snapcraft/scripts/bgpd-service | 9 | ||||
| -rwxr-xr-x | snapcraft/scripts/set-options | 25 | ||||
| -rw-r--r-- | snapcraft/snapcraft.yaml.in | 25 | ||||
| -rw-r--r-- | staticd/static_vty.c | 24 | ||||
| -rw-r--r-- | staticd/static_zebra.c | 7 | ||||
| -rw-r--r-- | tests/bgpd/test_capability.c | 2 | ||||
| -rw-r--r-- | zebra/redistribute.c | 7 | ||||
| -rw-r--r-- | zebra/redistribute.h | 3 | ||||
| -rw-r--r-- | zebra/rib.h | 2 | ||||
| -rw-r--r-- | zebra/zebra_rib.c | 13 | ||||
| -rw-r--r-- | zebra/zebra_routemap.c | 136 |
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: @@ -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; } /* @@ -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); @@ -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); |
