clean-local: clean-python
.PHONY: clean-python
clean-python:
- find -name __pycache__ -o -name .pytest_cache | xargs rm -rf
- find -name "*.pyc" -o -name "*_clippy.c" | xargs rm -f
+ find . -name __pycache__ -o -name .pytest_cache | xargs rm -rf
+ find . -name "*.pyc" -o -name "*_clippy.c" | xargs rm -f
redistclean:
$(MAKE) distclean CONFIG_CLEAN_FILES="$(filter-out $(EXTRA_DIST), $(CONFIG_CLEAN_FILES))"
}
void
-babel_if_init ()
+babel_if_init(void)
{
/* initialize interface list */
hook_register_prio(if_add, 0, babel_if_new_hook);
/* Delete all the added babel routes, make babeld only speak to zebra. */
static void
-babel_clean_routing_process()
+babel_clean_routing_process(void)
{
flush_all_routes();
babel_interface_close_all();
}
void
-update_myseqno()
+update_myseqno(void)
{
myseqno = seqno_plus(myseqno, 1);
}
}
unsigned
-check_neighbours()
+check_neighbours(void)
{
struct neighbour *neigh;
int changed, rc;
}
void
-expire_resend()
+expire_resend(void)
{
struct resend *current, *previous;
int recompute = 0;
}
void
-recompute_resend_time()
+recompute_resend_time(void)
{
struct resend *request;
struct timeval resend = {0, 0};
}
void
-do_resend()
+do_resend(void)
{
struct resend *resend;
}
void
-flush_all_routes()
+flush_all_routes(void)
{
int i;
}
void
-expire_sources()
+expire_sources(void)
{
struct source *src;
}
int
-daemonise()
+daemonise(void)
{
int rc;
/* Returns an overestimate of the number of xroutes. */
int
-xroutes_estimate()
+xroutes_estimate(void)
{
return numxroutes;
}
/* Install EVPN route into zebra. */
static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
- struct prefix_evpn *p,
- struct in_addr remote_vtep_ip, uint8_t flags,
- uint32_t seq)
+ struct prefix_evpn *p, struct bgp_path_info *pi)
{
int ret;
+ uint8_t flags;
- if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
- ret = bgp_zebra_send_remote_macip(bgp, vpn, p, remote_vtep_ip,
- 1, flags, seq);
- else
+ if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
+ flags = 0;
+ if (pi->attr->sticky)
+ SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
+ if (pi->attr->default_gw)
+ SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
+ if (is_evpn_prefix_ipaddr_v6(p) &&
+ pi->attr->router_flag)
+ SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
+ ret = bgp_zebra_send_remote_macip(
+ bgp, vpn, p, pi->attr->nexthop, 1, flags,
+ mac_mobility_seqnum(pi->attr));
+ } else {
ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, 1);
+ }
return ret;
}
{
struct bgp_path_info *old_select, *new_select;
struct bgp_path_info_pair old_and_new;
- struct prefix_evpn *evp;
afi_t afi = AFI_L2VPN;
safi_t safi = SAFI_EVPN;
int ret = 0;
- uint8_t flags = 0;
/* Compute the best path. */
bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], &old_and_new,
old_select = old_and_new.old;
new_select = old_and_new.new;
- evp = (struct prefix_evpn *)&rn->p;
/* If the best path hasn't changed - see if there is still something to
* update
* to zebra RIB.
&& !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR)
&& !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
&& !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
- if (bgp_zebra_has_route_changed(rn, old_select)) {
- if (old_select->attr->sticky)
- SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
- if (old_select->attr->default_gw)
- SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
- if (is_evpn_prefix_ipaddr_v6(evp) &&
- old_select->attr->router_flag)
- SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
-
+ if (bgp_zebra_has_route_changed(rn, old_select))
ret = evpn_zebra_install(
bgp, vpn, (struct prefix_evpn *)&rn->p,
- old_select->attr->nexthop, flags,
- mac_mobility_seqnum(old_select->attr));
- }
+ old_select);
UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
bgp_zebra_clear_route_change_flags(rn);
return ret;
if (new_select && new_select->type == ZEBRA_ROUTE_BGP
&& new_select->sub_type == BGP_ROUTE_IMPORTED) {
- flags = 0;
- if (new_select->attr->sticky)
- SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
- if (new_select->attr->default_gw)
- SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
- if (is_evpn_prefix_ipaddr_v6(evp) &&
- new_select->attr->router_flag)
- SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
-
ret = evpn_zebra_install(bgp, vpn, (struct prefix_evpn *)&rn->p,
- new_select->attr->nexthop, flags,
- mac_mobility_seqnum(new_select->attr));
+ new_select);
+
/* If an old best existed and it was a "local" route, the only
* reason
* it would be supplanted is due to MAC mobility procedures. So,
return route_change;
}
+static void evpn_zebra_reinstall_best_route(struct bgp *bgp,
+ struct bgpevpn *vpn, struct bgp_node *rn)
+{
+ struct bgp_path_info *tmp_ri;
+ struct bgp_path_info *curr_select = NULL;
+
+ for (tmp_ri = bgp_node_get_bgp_path_info(rn);
+ tmp_ri; tmp_ri = tmp_ri->next) {
+ if (CHECK_FLAG(tmp_ri->flags, BGP_PATH_SELECTED)) {
+ curr_select = tmp_ri;
+ break;
+ }
+ }
+
+ if (curr_select && curr_select->type == ZEBRA_ROUTE_BGP
+ && curr_select->sub_type == BGP_ROUTE_IMPORTED)
+ evpn_zebra_install(bgp, vpn,
+ (struct prefix_evpn *)&rn->p,
+ curr_select);
+}
+
/*
* If the local route was not selected evict it and tell zebra to re-add
* the best remote dest.
struct bgp_node *rn,
struct bgp_path_info *local_pi)
{
- struct bgp_path_info *tmp_pi;
- struct bgp_path_info *curr_select = NULL;
- uint8_t flags = 0;
char buf[PREFIX_STRLEN];
/* local path was not picked as the winner; kick it out */
bgp_path_info_reap(rn, local_pi);
/* tell zebra to re-add the best remote path */
- for (tmp_pi = bgp_node_get_bgp_path_info(rn);
- tmp_pi; tmp_pi = tmp_pi->next) {
- if (CHECK_FLAG(tmp_pi->flags, BGP_PATH_SELECTED)) {
- curr_select = tmp_pi;
- break;
- }
- }
- if (curr_select &&
- curr_select->type == ZEBRA_ROUTE_BGP
- && curr_select->sub_type == BGP_ROUTE_IMPORTED) {
- if (curr_select->attr->sticky)
- SET_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
- if (curr_select->attr->default_gw)
- SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
- evpn_zebra_install(bgp, vpn, (struct prefix_evpn *)&rn->p,
- curr_select->attr->nexthop, flags,
- mac_mobility_seqnum(curr_select->attr));
- }
+ evpn_zebra_reinstall_best_route(bgp, vpn, rn);
}
/*
* Handle del of a local MACIP.
*/
int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni, struct ethaddr *mac,
- struct ipaddr *ip)
+ struct ipaddr *ip, int state)
{
struct bgpevpn *vpn;
struct prefix_evpn p;
+ struct bgp_node *rn;
/* Lookup VNI hash - should exist. */
vpn = bgp_evpn_lookup_vni(bgp, vni);
return -1;
}
- /* Remove EVPN type-2 route and schedule for processing. */
build_evpn_type2_prefix(&p, mac, ip);
- delete_evpn_route(bgp, vpn, &p);
+ if (state == ZEBRA_NEIGH_ACTIVE) {
+ /* Remove EVPN type-2 route and schedule for processing. */
+ delete_evpn_route(bgp, vpn, &p);
+ } else {
+ /* Re-instate the current remote best path if any */
+ rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
+ if (rn)
+ evpn_zebra_reinstall_best_route(bgp, vpn, rn);
+ }
return 0;
}
struct prefix *p, struct bgp_path_info *ri);
extern int bgp_filter_evpn_routes_upon_martian_nh_change(struct bgp *bgp);
extern int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni,
- struct ethaddr *mac, struct ipaddr *ip);
+ struct ethaddr *mac, struct ipaddr *ip,
+ int state);
extern int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni,
struct ethaddr *mac, struct ipaddr *ip,
uint8_t flags, uint32_t seq);
pthread_mutex_unlock(peerhash_mtx);
}
-void bgp_keepalives_wake()
+void bgp_keepalives_wake(void)
{
pthread_mutex_lock(peerhash_mtx);
{
/********************
* PUBLIC FUNCTIONS
********************/
-struct bpacket *bpacket_alloc()
+struct bpacket *bpacket_alloc(void)
{
struct bpacket *pkt;
#include "command.h"
#include "lib/json.h"
+#include "lib/zclient.h"
#include "prefix.h"
#include "plist.h"
#include "buffer.h"
return CMD_WARNING;
}
- rv = bgp_evpn_local_macip_del(bgp, vni, &mac, &ip);
+ rv = bgp_evpn_local_macip_del(bgp, vni, &mac, &ip, ZEBRA_NEIGH_ACTIVE);
if (rv < 0) {
vty_out(vty, "Internal error\n");
return CMD_WARNING;
switch (ret) {
case BGP_ERR_PEER_GROUP_MEMBER:
vty_out(vty,
- "%% Peer-group AS %u. Cannot configure remote-as for member\n",
- as);
+ "%% Peer-group member cannot override remote-as of peer-group\n");
return CMD_WARNING_CONFIG_FAILED;
case BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT:
vty_out(vty,
- "%% The AS# can not be changed from %u to %s, peer-group members must be all internal or all external\n",
- as, as_str);
+ "%% Peer-group members must be all internal or all external\n");
return CMD_WARNING_CONFIG_FAILED;
}
return bgp_vty_return(vty, ret);
if (!CHECK_FLAG(peer->flags_invert, PEER_FLAG_CAPABILITY_ENHE)) {
SET_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE);
SET_FLAG(peer->flags_invert, PEER_FLAG_CAPABILITY_ENHE);
- UNSET_FLAG(peer->flags_override, PEER_FLAG_CAPABILITY_ENHE);
+ SET_FLAG(peer->flags_override, PEER_FLAG_CAPABILITY_ENHE);
}
if (peer_group_name) {
? " replace-as"
: "");
}
- /* peer type internal, external, confed-internal or confed-external */
- if (p->as == p->local_as) {
+ /* peer type internal or confed-internal */
+ if ((p->as == p->local_as) || (p->as_type == AS_INTERNAL)) {
if (use_json) {
if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
json_object_boolean_true_add(
else
vty_out(vty, "internal link\n");
}
- } else {
+ /* peer type external or confed-external */
+ } else if (p->as || (p->as_type == AS_EXTERNAL)) {
if (use_json) {
if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
json_object_boolean_true_add(
else
vty_out(vty, "external link\n");
}
+ } else {
+ if (use_json)
+ json_object_boolean_true_add(json_neigh,
+ "nbrUnspecifiedLink");
+ else
+ vty_out(vty, "unspecified link\n");
}
/* Description. */
bgp_show_neighbor(vty, bgp, show_all, NULL, NULL,
use_json, json);
}
+ json_object_free(json);
}
if (use_json) {
char buf1[INET6_ADDRSTRLEN];
uint8_t flags = 0;
uint32_t seqnum = 0;
+ int state = 0;
memset(&ip, 0, sizeof(ip));
s = zclient->ibuf;
if (command == ZEBRA_MACIP_ADD) {
flags = stream_getc(s);
seqnum = stream_getl(s);
+ } else {
+ state = stream_getl(s);
}
bgp = bgp_lookup_by_vrf_id(vrf_id);
return 0;
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("%u:Recv MACIP %s flags 0x%x MAC %s IP %s VNI %u seq %u",
+ zlog_debug("%u:Recv MACIP %s flags 0x%x MAC %s IP %s VNI %u seq %u state %d",
vrf_id, (command == ZEBRA_MACIP_ADD) ? "Add" : "Del",
flags, prefix_mac2str(&mac, buf, sizeof(buf)),
- ipaddr2str(&ip, buf1, sizeof(buf1)), vni, seqnum);
+ ipaddr2str(&ip, buf1, sizeof(buf1)), vni, seqnum,
+ state);
if (command == ZEBRA_MACIP_ADD)
return bgp_evpn_local_macip_add(bgp, vni, &mac, &ip,
flags, seqnum);
else
- return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip);
+ return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip, state);
}
static void bgp_zebra_process_local_ip_prefix(int cmd, struct zclient *zclient,
return BGP_PEER_EBGP;
} else {
- if (peer->as_type != AS_SPECIFIED)
+ if (peer->as_type == AS_UNSPECIFIED) {
+ /* check if in peer-group with AS information */
+ if (peer->group
+ && (peer->group->conf->as_type != AS_UNSPECIFIED)) {
+ if (peer->group->conf->as_type
+ == AS_SPECIFIED) {
+ if (peer->local_as
+ == peer->group->conf->as)
+ return BGP_PEER_IBGP;
+ else
+ return BGP_PEER_EBGP;
+ } else if (peer->group->conf->as_type
+ == AS_INTERNAL)
+ return BGP_PEER_IBGP;
+ else
+ return BGP_PEER_EBGP;
+ }
+ /* no AS information anywhere, let caller know */
+ return BGP_PEER_UNSPECIFIED;
+ } else if (peer->as_type != AS_SPECIFIED)
return (peer->as_type == AS_INTERNAL ? BGP_PEER_IBGP
: BGP_PEER_EBGP);
/* When this peer is a member of peer-group. */
if (peer->group) {
- if (peer->group->conf->as) {
+ /* peer-group already has AS number/internal/external */
+ if (peer->group->conf->as
+ || peer->group->conf->as_type) {
/* Return peer group's AS number. */
*as = peer->group->conf->as;
return BGP_ERR_PEER_GROUP_MEMBER;
}
- if (peer_sort(peer->group->conf) == BGP_PEER_IBGP) {
- if ((as_type != AS_INTERNAL)
- && (bgp->as != *as)) {
+
+ bgp_peer_sort_t peer_sort_type =
+ peer_sort(peer->group->conf);
+
+ /* Explicit AS numbers used, compare AS numbers */
+ if (as_type == AS_SPECIFIED) {
+ if (((peer_sort_type == BGP_PEER_IBGP)
+ && (bgp->as != *as))
+ || ((peer_sort_type == BGP_PEER_EBGP)
+ && (bgp->as == *as))) {
*as = peer->as;
return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
}
} else {
- if ((as_type != AS_EXTERNAL)
- && (bgp->as == *as)) {
+ /* internal/external used, compare as-types */
+ if (((peer_sort_type == BGP_PEER_IBGP)
+ && (as_type != AS_INTERNAL))
+ || ((peer_sort_type == BGP_PEER_EBGP)
+ && (as_type != AS_EXTERNAL))) {
*as = peer->as;
return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
}
if (peer->as_type == AS_UNSPECIFIED) {
peer->as_type = group->conf->as_type;
peer->as = group->conf->as;
+ peer->sort = group->conf->sort;
}
if (!group->conf->as) {
/* capability extended-nexthop */
if (peergroup_flag_check(peer, PEER_FLAG_CAPABILITY_ENHE)) {
- if (CHECK_FLAG(peer->flags_invert, PEER_FLAG_CAPABILITY_ENHE))
- vty_out(vty,
- " no neighbor %s capability extended-nexthop\n",
- addr);
- else
- vty_out(vty,
- " neighbor %s capability extended-nexthop\n",
- addr);
+ if (!peer->conf_if) {
+ if (CHECK_FLAG(peer->flags_invert,
+ PEER_FLAG_CAPABILITY_ENHE))
+ vty_out(vty,
+ " no neighbor %s capability extended-nexthop\n",
+ addr);
+ else
+ vty_out(vty,
+ " neighbor %s capability extended-nexthop\n",
+ addr);
+ }
}
/* dont-capability-negotiation */
struct frr_pthread *bgp_pth_io;
struct frr_pthread *bgp_pth_ka;
-static void bgp_pthreads_init()
+static void bgp_pthreads_init(void)
{
assert(!bgp_pth_io);
assert(!bgp_pth_ka);
bgp_pth_ka = frr_pthread_new(&ka, "BGP Keepalives thread", "bgpd_ka");
}
-void bgp_pthreads_run()
+void bgp_pthreads_run(void)
{
frr_pthread_run(bgp_pth_io, NULL);
frr_pthread_run(bgp_pth_ka, NULL);
frr_pthread_wait_running(bgp_pth_ka);
}
-void bgp_pthreads_finish()
+void bgp_pthreads_finish(void)
{
frr_pthread_stop_all();
frr_pthread_finish();
/* IBGP/EBGP identifier. We also have a CONFED peer, which is to say,
a peer who's AS is part of our Confederation. */
typedef enum {
- BGP_PEER_IBGP = 1,
+ BGP_PEER_UNSPECIFIED,
+ BGP_PEER_IBGP,
BGP_PEER_EBGP,
BGP_PEER_INTERNAL,
BGP_PEER_CONFED,
return NULL;
}
-static struct rfapi_l2_group_cfg *rfapi_l2_group_new()
+static struct rfapi_l2_group_cfg *rfapi_l2_group_new(void)
{
struct rfapi_l2_group_cfg *rfg;
return CMD_SUCCESS;
}
-static struct rfapi_rfg_name *rfgn_new()
+static struct rfapi_rfg_name *rfgn_new(void)
{
return XCALLOC(MTYPE_RFAPI_RFG_NAME, sizeof(struct rfapi_rfg_name));
}
* Count remote routes and compare with actively-maintained values.
* Abort if they disagree.
*/
-void rfapiCheckRouteCount()
+void rfapiCheckRouteCount(void)
{
struct bgp *bgp = bgp_get_default();
struct rfapi *h;
assert(t_ri_active + t_ri_deleted + t_ri_pend + offset == alloc_count);
}
-static struct rfapi_info *rfapi_info_new()
+static struct rfapi_info *rfapi_info_new(void)
{
return XCALLOC(MTYPE_RFAPI_INFO, sizeof(struct rfapi_info));
}
return vnc_clear_vrf(vty, NULL, arg_vrf, NULL, NULL);
}
-void rfapi_vty_init()
+void rfapi_vty_init(void)
{
install_element(ENABLE_NODE, &add_vnc_prefix_cost_life_lnh_cmd);
install_element(ENABLE_NODE, &add_vnc_prefix_life_cost_lnh_cmd);
return CMD_SUCCESS;
}
-static void rfp_vty_install()
+static void rfp_vty_install(void)
{
static int installed = 0;
if (installed) /* do this only once */
#include <stdio.h>
#include <stdlib.h>
#include "rfptest.h"
-int main()
+int main(void)
{
printf("Your test code goes here.\n");
exit(1);
dnl $AR and $RANLIB are set by LT_INIT above
AC_MSG_CHECKING([whether $AR supports D option])
-if $AR crD conftest.a; then
+if $AR crD conftest.a >/dev/null 2>/dev/null; then
AC_MSG_RESULT([yes])
dnl ARFLAGS is for automake, AR_FLAGS for libtool m-(
ARFLAGS="crD"
AC_SUBST([AR_FLAGS])
AC_MSG_CHECKING([whether $RANLIB supports D option])
-if $RANLIB -D conftest.a; then
+if $RANLIB -D conftest.a >/dev/null 2>/dev/null; then
AC_MSG_RESULT([yes])
RANLIB="$RANLIB -D"
else
AM_CONDITIONAL([GIT_VERSION], [test "x$with_pkg_git_version" = "xyes"])
AC_CHECK_TOOL([OBJCOPY], [objcopy], [:])
-AC_CACHE_CHECK([for .interp value to use], [frr_cv_interp], [
- frr_cv_interp=""
- AC_LINK_IFELSE([AC_LANG_SOURCE([[int main() { return 0; }]])], [
- if $OBJCOPY -j.interp -Obinary conftest conftest.interp; then
- frr_cv_interp="`xargs -0 echo < conftest.interp`"
- fi
- test -f conftest.interp && rm conftest.interp
+if test "x${OBJCOPY}" != "x:"; then
+ AC_CACHE_CHECK([for .interp value to use], [frr_cv_interp], [
+ frr_cv_interp=""
+ AC_LINK_IFELSE([AC_LANG_SOURCE([[int main() { return 0; }]])], [
+ if $OBJCOPY -j.interp -Obinary conftest conftest.interp; then
+ frr_cv_interp="`xargs -0 echo < conftest.interp`"
+ fi
+ test -f conftest.interp && rm conftest.interp
+ ])
])
-])
+fi
if test -n "$frr_cv_interp"; then
AC_DEFINE_UNQUOTED([INTERP], ["$frr_cv_interp"], [.interp value])
fi
])
], [[#include <libyang/libyang.h>]])
+ac_ld_flag_save="$LDFLAGS"
+LDFLAGS="$LDFLAGS $libyang_LIBS"
+AC_CHECK_FUNC([ly_register_types], [
+ libyang_ext_builtin=true
+ AC_DEFINE([LIBYANG_EXT_BUILTIN], [1], [have ly_register_types()])
+], [
+ libyang_ext_builtin=false
+ AC_MSG_WARN([===== old libyang (before 0.16.74) detected =====])
+ AC_MSG_WARN([The available version of libyang does not seem to support])
+ AC_MSG_WARN([built-in YANG extension modules. This will cause "make check"])
+ AC_MSG_WARN([to fail and may create installation and version mismatch issues.])
+ AC_MSG_WARN([Support for the old mechanism will be removed at some point.])
+ AC_MSG_WARN([Please update libyang to version 0.16.74 or newer.])
+ AC_MSG_WARN([===== old libyang (before 0.16.74) detected =====])
+])
+AM_CONDITIONAL([LIBYANG_EXT_BUILTIN], [$libyang_ext_builtin])
+LDFLAGS="$ac_ld_flag_save"
+
dnl ---------------
dnl configuration rollbacks
dnl ---------------
Note: the libyang dev/devel packages need to be installed in addition
to the libyang core package in order to build FRR successfully.
+.. warning::
+ libyang ABI version 0.16.74 or newer will be required to build FRR in the
+ near future since it significantly eases build and installation
+ considerations. "0.16-r3" is equal to 0.16.105 and will work, "0.16-r2"
+ is equal to 0.16.52 and will stop working. The CI artifacts will be
+ updated shortly.
+
For example, for CentOS 7.x:
.. code-block:: shell
sudo apt install libpcre3-dev
sudo dpkg -i libyang-dev_0.16.46_amd64.deb libyang_0.16.46_amd64.deb
+.. note::
+ For Debian-based systems, the official libyang package requires recent
+ versions of swig (3.0.12) and debhelper (11) which are only available in
+ Debian buster (10). However, libyang packages built on Debian buster can
+ be installed on both Debian jessie (8) and Debian stretch (9), as well as
+ various Ubuntu systems. The python3-yang package will not work, but the
+ other packages (libyang-dev is the one needed for FRR) will.
+
Alternatively, libyang can be built and installed manually by following
the steps below:
#include "hook.h"
#include "module.h"
+ #include "libfrr.h"
+ #include "thread.h"
+
+ static int module_late_init(struct thread_master *master)
+ {
+ /* Do initialization stuff here */
+ return 0;
+ }
static int
module_init (void)
Look for libyang plugins in `dir` [`prefix`/lib/frr/libyang_plugins].
Note that the FRR libyang plugins will be installed here.
+ This option is meaningless with libyang 0.16.74 or newer and will be
+ removed once support for older libyang versions is dropped.
+
When it's desired to run FRR without installing it in the system, it's possible
to configure it as follows to look for YANG modules and libyang plugins in the
compile directory:
};
/* Initialize debug commands. */
-void eigrp_debug_init()
+void eigrp_debug_init(void)
{
install_node(&eigrp_debug_node, config_write_debug);
struct list *eigrp_iflist;
-void eigrp_if_init()
+void eigrp_if_init(void)
{
/* Initialize Zebra interface data structure. */
// hook_register_prio(if_add, 0, eigrp_if_new);
return new;
}
-static struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new()
+static struct TLV_IPv4_Internal_type *eigrp_IPv4_InternalTLV_new(void)
{
struct TLV_IPv4_Internal_type *new;
return 0;
}
-struct TLV_MD5_Authentication_Type *eigrp_authTLV_MD5_new()
+struct TLV_MD5_Authentication_Type *eigrp_authTLV_MD5_new(void)
{
struct TLV_MD5_Authentication_Type *new;
XFREE(MTYPE_EIGRP_AUTH_TLV, authTLV);
}
-struct TLV_SHA256_Authentication_Type *eigrp_authTLV_SHA256_new()
+struct TLV_SHA256_Authentication_Type *eigrp_authTLV_SHA256_new(void)
{
struct TLV_SHA256_Authentication_Type *new;
XFREE(MTYPE_EIGRP_IPV4_INT_TLV, IPv4_InternalTLV);
}
-struct TLV_Sequence_Type *eigrp_SequenceTLV_new()
+struct TLV_Sequence_Type *eigrp_SequenceTLV_new(void)
{
struct TLV_Sequence_Type *new;
* del - assigned function executed before deleting topology node by list
* function
*/
-struct route_table *eigrp_topology_new()
+struct route_table *eigrp_topology_new(void)
{
return route_table_init();
}
* Returns new created toplogy node
* cmp - assigned function for comparing topology entry
*/
-struct eigrp_prefix_entry *eigrp_prefix_entry_new()
+struct eigrp_prefix_entry *eigrp_prefix_entry_new(void)
{
struct eigrp_prefix_entry *new;
new = XCALLOC(MTYPE_EIGRP_PREFIX_ENTRY,
* Returns new topology entry
*/
-struct eigrp_nexthop_entry *eigrp_nexthop_entry_new()
+struct eigrp_nexthop_entry *eigrp_nexthop_entry_new(void)
{
struct eigrp_nexthop_entry *new;
}
}
-void eigrp_master_init()
+void eigrp_master_init(void)
{
struct timeval tv;
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LINUX_IF_ADDR_H
+#define __LINUX_IF_ADDR_H
+
+#include <linux/types.h>
+#include <linux/netlink.h>
+
+struct ifaddrmsg {
+ __u8 ifa_family;
+ __u8 ifa_prefixlen; /* The prefix length */
+ __u8 ifa_flags; /* Flags */
+ __u8 ifa_scope; /* Address scope */
+ __u32 ifa_index; /* Link index */
+};
+
+/*
+ * Important comment:
+ * IFA_ADDRESS is prefix address, rather than local interface address.
+ * It makes no difference for normally configured broadcast interfaces,
+ * but for point-to-point IFA_ADDRESS is DESTINATION address,
+ * local address is supplied in IFA_LOCAL attribute.
+ *
+ * IFA_FLAGS is a u32 attribute that extends the u8 field ifa_flags.
+ * If present, the value from struct ifaddrmsg will be ignored.
+ */
+enum {
+ IFA_UNSPEC,
+ IFA_ADDRESS,
+ IFA_LOCAL,
+ IFA_LABEL,
+ IFA_BROADCAST,
+ IFA_ANYCAST,
+ IFA_CACHEINFO,
+ IFA_MULTICAST,
+ IFA_FLAGS,
+ IFA_RT_PRIORITY, /* u32, priority/metric for prefix route */
+ __IFA_MAX,
+};
+
+#define IFA_MAX (__IFA_MAX - 1)
+
+/* ifa_flags */
+#define IFA_F_SECONDARY 0x01
+#define IFA_F_TEMPORARY IFA_F_SECONDARY
+
+#define IFA_F_NODAD 0x02
+#define IFA_F_OPTIMISTIC 0x04
+#define IFA_F_DADFAILED 0x08
+#define IFA_F_HOMEADDRESS 0x10
+#define IFA_F_DEPRECATED 0x20
+#define IFA_F_TENTATIVE 0x40
+#define IFA_F_PERMANENT 0x80
+#define IFA_F_MANAGETEMPADDR 0x100
+#define IFA_F_NOPREFIXROUTE 0x200
+#define IFA_F_MCAUTOJOIN 0x400
+#define IFA_F_STABLE_PRIVACY 0x800
+
+struct ifa_cacheinfo {
+ __u32 ifa_prefered;
+ __u32 ifa_valid;
+ __u32 cstamp; /* created timestamp, hundredths of seconds */
+ __u32 tstamp; /* updated timestamp, hundredths of seconds */
+};
+
+/* backwards compatibility for userspace */
+#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
+#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg))
+
+#endif
noinst_HEADERS += \
+ include/linux/if_addr.h \
include/linux/if_bridge.h \
include/linux/if_link.h \
include/linux/lwtunnel.h \
int isis_if_new_hook(struct interface *);
int isis_if_delete_hook(struct interface *);
-struct isis_circuit *isis_circuit_new()
+struct isis_circuit *isis_circuit_new(void)
{
struct isis_circuit *circuit;
int i;
return 0;
}
-void isis_circuit_init()
+void isis_circuit_init(void)
{
/* Initialize Zebra interface data structure */
hook_register_prio(if_add, 0, isis_if_new_hook);
return CMD_SUCCESS;
}
-void isis_spf_cmds_init()
+void isis_spf_cmds_init(void)
{
install_element(VIEW_NODE, &show_isis_topology_cmd);
}
*------------------------------------------------------------------------*/
/* Create new MPLS TE Circuit context */
-struct mpls_te_circuit *mpls_te_circuit_new()
+struct mpls_te_circuit *mpls_te_circuit_new(void)
{
struct mpls_te_circuit *mtc;
struct cmd_node router_node = {ROUTER_NODE, "%s(config-router)# ", 1};
-void isis_init()
+void isis_init(void)
{
/* Install IS-IS top node */
install_node(&router_node, isis_config_write);
{
int idx_log_levels = 2;
- disable_log_file();
-
if (argc == 3) {
int level;
if ((level = level_match(argv[idx_log_levels]->arg))
#endif
}
-void cmd_terminate()
+void cmd_terminate(void)
{
struct cmd_node *cmd_node;
install_element(CONFIG_NODE, &no_ipv6_access_list_remark_comment_cmd);
}
-void access_list_init()
+void access_list_init(void)
{
access_list_init_ipv4();
access_list_init_ipv6();
access_list_init_mac();
}
-void access_list_reset()
+void access_list_reset(void)
{
access_list_reset_ipv4();
access_list_reset_ipv6();
/* ------------------------------------------------------------------------ */
-void frr_pthread_init()
+void frr_pthread_init(void)
{
pthread_mutex_lock(&frr_pthread_list_mtx);
{
pthread_mutex_unlock(&frr_pthread_list_mtx);
}
-void frr_pthread_finish()
+void frr_pthread_finish(void)
{
pthread_mutex_lock(&frr_pthread_list_mtx);
{
#ifdef HAVE_PTHREAD_SETNAME_NP
# ifdef GNU_LINUX
ret = pthread_setname_np(fpt->thread, fpt->os_name);
-# else /* NetBSD */
+# elif defined(__NetBSD__)
ret = pthread_setname_np(fpt->thread, fpt->os_name, NULL);
# endif
#elif defined(HAVE_PTHREAD_SET_NAME_NP)
return ret;
}
-void frr_pthread_stop_all()
+void frr_pthread_stop_all(void)
{
pthread_mutex_lock(&frr_pthread_list_mtx);
{
DEFINE_MTYPE_STATIC(LIB, GRAPH, "Graph")
DEFINE_MTYPE_STATIC(LIB, GRAPH_NODE, "Graph Node")
-struct graph *graph_new()
+struct graph *graph_new(void)
{
struct graph *graph = XCALLOC(MTYPE_GRAPH, sizeof(struct graph));
graph->nodes = vector_init(VECTOR_MIN_SIZE);
return CMD_SUCCESS;
}
-void hash_cmd_init()
+void hash_cmd_init(void)
{
install_element(ENABLE_NODE, &show_hash_stats_cmd);
}
DECLARE_HOOK(if_add, (struct interface * ifp), (ifp))
DECLARE_KOOH(if_del, (struct interface * ifp), (ifp))
+#define METRIC_MAX (~0)
+
/* Connected address structure. */
struct connected {
/* Attached interface. */
/* Label for Linux 2.2.X and upper. */
char *label;
+
+ /*
+ * Used for setting the connected route's cost. If the metric
+ * here is set to METRIC_MAX the connected route falls back to
+ * "struct interface"
+ */
+ uint32_t metric;
};
/* Nbr Connected address structure. */
return write;
}
-void if_rmap_reset()
+void if_rmap_reset(void)
{
hash_clean(ifrmaphash, (void (*)(void *))if_rmap_free);
}
return 0;
}
-void keychain_init()
+void keychain_init(void)
{
keychain_list = list_new();
}
/* From RFC 2104 */
-void hmac_md5(text, text_len, key, key_len,
- digest) unsigned char *text; /* pointer to data stream */
-int text_len; /* length of data stream */
-unsigned char *key; /* pointer to authentication key */
-int key_len; /* length of authentication key */
-uint8_t *digest; /* caller digest to be filled in */
-
+void hmac_md5(unsigned char *text, int text_len, unsigned char *key,
+ int key_len, uint8_t *digest)
{
MD5_CTX context;
unsigned char k_ipad[65]; /* inner padding -
install_element(ENABLE_NODE, &clear_ipv6_prefix_list_cmd);
}
-void prefix_list_init()
+void prefix_list_init(void)
{
cmd_variable_handler_register(plist_var_handlers);
prefix_list_init_ipv6();
}
-void prefix_list_reset()
+void prefix_list_reset(void)
{
prefix_list_reset_afi(AFI_IP, 0);
prefix_list_reset_afi(AFI_IP6, 0);
}
/* Allocate new prefix_ipv4 structure. */
-struct prefix_ipv4 *prefix_ipv4_new()
+struct prefix_ipv4 *prefix_ipv4_new(void)
{
struct prefix_ipv4 *p;
return str;
}
-struct prefix *prefix_new()
+struct prefix *prefix_new(void)
{
struct prefix *p;
}
$str =~ s/ $//;
push @lines, $str . "\\n\" \\\n";
- push @lines, " \" > - selected route, * - FIB route\\n\\n\"";
+ push @lines, " \" > - selected route, * - FIB route, q - queued route, f - failed route\\n\\n\"";
return join("", @lines);
}
#endif
-static int randomLevel()
+static int randomLevel(void)
{
register int level = 0;
register int b;
orig = res;
- while (res) {
+ while (res && col < tt->ncols) {
section = strsep(&res, "|");
row[col].text = XSTRDUP(MTYPE_TTABLE, section);
row[col].style = tt->style.cell;
}
/* initializer, only ever called once */
-static void initializer()
+static void initializer(void)
{
pthread_key_create(&thread_current, NULL);
}
}
/* Allocate new vty struct. */
-struct vty *vty_new()
+struct vty *vty_new(void)
{
struct vty *new = XCALLOC(MTYPE_VTY, sizeof(struct vty));
};
/* Reset all VTY status. */
-void vty_reset()
+void vty_reset(void)
{
unsigned int i;
struct vty *vty;
strcpy(vty_cwd, cwd);
}
-char *vty_get_cwd()
+char *vty_get_cwd(void)
{
return vty_cwd;
}
return vty->type == VTY_SHELL_SERV ? 1 : 0;
}
-void vty_init_vtysh()
+void vty_init_vtysh(void)
{
vtyvec = vector_init(VECTOR_MIN_SIZE);
}
#include "yang_translator.h"
#include "northbound.h"
+#include <libyang/user_types.h>
+
DEFINE_MTYPE(LIB, YANG_MODULE, "YANG module")
DEFINE_MTYPE(LIB, YANG_DATA, "YANG data structure")
zlog(priority, "libyang: %s", msg);
}
+#if CONFDATE > 20190401
+CPP_NOTICE("lib/yang: time to remove non-LIBYANG_EXT_BUILTIN support")
+#endif
+
+#ifdef LIBYANG_EXT_BUILTIN
+extern struct lytype_plugin_list frr_user_types[];
+#endif
+
void yang_init(void)
{
+#ifndef LIBYANG_EXT_BUILTIN
+CPP_NOTICE("lib/yang: deprecated libyang <0.16.74 extension loading in use!")
static char ly_plugin_dir[PATH_MAX];
const char *const *ly_loaded_plugins;
const char *ly_plugin;
snprintf(ly_plugin_dir, sizeof(ly_plugin_dir), "%s=%s",
"LIBYANG_USER_TYPES_PLUGINS_DIR", LIBYANG_PLUGINS_PATH);
putenv(ly_plugin_dir);
+#endif
/* Initialize libyang global parameters that affect all containers. */
ly_set_log_clb(ly_log_cb, 1);
ly_log_options(LY_LOLOG | LY_LOSTORE);
+#ifdef LIBYANG_EXT_BUILTIN
+ if (ly_register_types(frr_user_types, "frr_user_types")) {
+ flog_err(EC_LIB_LIBYANG_PLUGIN_LOAD,
+ "ly_register_types() failed");
+ exit(1);
+ }
+#endif
+
/* Initialize libyang container for native models. */
ly_native_ctx =
ly_ctx_new(YANG_MODELS_PATH, LY_CTX_DISABLE_SEARCHDIR_CWD);
ly_ctx_set_module_imp_clb(ly_native_ctx, yang_module_imp_clb, NULL);
ly_ctx_set_priv_dup_clb(ly_native_ctx, ly_dup_cb);
+#ifndef LIBYANG_EXT_BUILTIN
/* Detect if the required libyang plugin(s) were loaded successfully. */
ly_loaded_plugins = ly_get_loaded_plugins();
for (size_t i = 0; (ly_plugin = ly_loaded_plugins[i]); i++) {
"%s: failed to load frr_user_types.so", __func__);
exit(1);
}
+#endif
yang_translator_init();
}
#define ZEBRA_MACIP_TYPE_ROUTER_FLAG 0x04 /* Router Flag - proxy NA */
#define ZEBRA_MACIP_TYPE_OVERRIDE_FLAG 0x08 /* Override Flag */
+enum zebra_neigh_state { ZEBRA_NEIGH_INACTIVE = 0, ZEBRA_NEIGH_ACTIVE = 1 };
+
struct zclient_options {
bool receive_notify;
};
return 0;
}
-void install_element_ospf6_debug_asbr()
+void install_element_ospf6_debug_asbr(void)
{
install_element(ENABLE_NODE, &debug_ospf6_asbr_cmd);
install_element(ENABLE_NODE, &no_debug_ospf6_asbr_cmd);
THREAD_OFF(oi->thread_send_hello);
THREAD_OFF(oi->thread_send_lsupdate);
THREAD_OFF(oi->thread_send_lsack);
+ THREAD_OFF(oi->thread_sso);
ospf6_lsdb_remove_all(oi->lsdb);
ospf6_lsdb_remove_all(oi->lsupdate_list);
THREAD_OFF(oi->thread_send_hello);
THREAD_OFF(oi->thread_send_lsupdate);
THREAD_OFF(oi->thread_send_lsack);
+ THREAD_OFF(oi->thread_sso);
THREAD_OFF(oi->thread_network_lsa);
THREAD_OFF(oi->thread_link_lsa);
if (if_is_operative(ifp)
&& (ospf6_interface_get_linklocal_address(oi->interface)
|| if_is_loopback(oi->interface)))
- thread_add_event(master, interface_up, oi, 0, NULL);
+ thread_execute(master, interface_up, oi, 0);
else
- thread_add_event(master, interface_down, oi, 0, NULL);
+ thread_execute(master, interface_down, oi, 0);
return;
}
oi = (struct ospf6_interface *)THREAD_ARG(thread);
assert(oi && oi->interface);
+ /*
+ * Remove old pointer. If this thread wasn't a timer this
+ * operation won't make a difference, because it is already NULL.
+ */
+ oi->thread_sso = NULL;
+
if (IS_OSPF6_DEBUG_INTERFACE)
zlog_debug("Interface Event %s: [InterfaceUp]",
oi->interface->name);
return 0;
}
+#ifdef __FreeBSD__
+ /*
+ * XXX: Schedule IPv6 group join for later, otherwise we might
+ * lose the multicast group registration caused by IPv6 group
+ * leave race.
+ */
+ if (oi->sso_try_cnt == 0) {
+ oi->sso_try_cnt++;
+ zlog_info("Scheduling %s for sso", oi->interface->name);
+ thread_add_timer(master, interface_up, oi,
+ OSPF6_INTERFACE_SSO_RETRY_INT,
+ &oi->thread_sso);
+ return 0;
+ }
+#endif /* __FreeBSD__ */
+
/* Join AllSPFRouters */
if (ospf6_sso(oi->interface->ifindex, &allspfrouters6, IPV6_JOIN_GROUP)
< 0) {
"Scheduling %s for sso retry, trial count: %d",
oi->interface->name, oi->sso_try_cnt);
thread_add_timer(master, interface_up, oi,
- OSPF6_INTERFACE_SSO_RETRY_INT, NULL);
+ OSPF6_INTERFACE_SSO_RETRY_INT,
+ &oi->thread_sso);
}
return 0;
}
/* Stop Hellos */
THREAD_OFF(oi->thread_send_hello);
+ /* Stop trying to set socket options. */
+ THREAD_OFF(oi->thread_sso);
+
/* Leave AllSPFRouters */
if (oi->state > OSPF6_INTERFACE_DOWN)
ospf6_sso(oi->interface->ifindex, &allspfrouters6,
SET_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE);
THREAD_OFF(oi->thread_send_hello);
+ THREAD_OFF(oi->thread_sso);
for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
THREAD_OFF(on->inactivity_timer);
UNSET_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE);
THREAD_OFF(oi->thread_send_hello);
- oi->thread_send_hello = NULL;
+ THREAD_OFF(oi->thread_sso);
thread_add_event(master, ospf6_hello_send, oi, 0,
&oi->thread_send_hello);
}
/* Reset the interface */
- thread_add_event(master, interface_down, oi, 0, NULL);
- thread_add_event(master, interface_up, oi, 0, NULL);
+ thread_execute(master, interface_down, oi, 0);
+ thread_execute(master, interface_up, oi, 0);
return CMD_SUCCESS;
}
oi->type = type;
/* Reset the interface */
- thread_add_event(master, interface_down, oi, 0, NULL);
- thread_add_event(master, interface_up, oi, 0, NULL);
+ thread_execute(master, interface_down, oi, 0);
+ thread_execute(master, interface_up, oi, 0);
return CMD_SUCCESS;
}
zlog_debug("Interface %s: clear by reset", ifp->name);
/* Reset the interface */
- thread_add_event(master, interface_down, oi, 0, NULL);
- thread_add_event(master, interface_up, oi, 0, NULL);
+ thread_execute(master, interface_down, oi, 0);
+ thread_execute(master, interface_up, oi, 0);
}
/* Clear interface */
/* Interface socket setting trial counter, resets on success */
uint8_t sso_try_cnt;
+ struct thread *thread_sso;
/* OSPF6 Interface flag */
char flag;
* -----------------------------------------------------------
*/
-struct msg_fifo *msg_fifo_new()
+struct msg_fifo *msg_fifo_new(void)
{
return XCALLOC(MTYPE_OSPF_API_FIFO, sizeof(struct msg_fifo));
}
}
-struct crypt_key *ospf_crypt_key_new()
+struct crypt_key *ospf_crypt_key_new(void)
{
return XCALLOC(MTYPE_OSPF_CRYPT_KEY, sizeof(struct crypt_key));
}
return OSPF_IFTYPE_BROADCAST;
}
-void ospf_if_init()
+void ospf_if_init(void)
{
/* Initialize Zebra interface data structure. */
hook_register_prio(if_add, 0, ospf_if_new_hook);
/* Create OSPF LSA. */
-struct ospf_lsa *ospf_lsa_new()
+struct ospf_lsa *ospf_lsa_new(void)
{
struct ospf_lsa *new;
#include "ospfd/ospf_lsa.h"
#include "ospfd/ospf_lsdb.h"
-struct ospf_lsdb *ospf_lsdb_new()
+struct ospf_lsdb *ospf_lsdb_new(void)
{
struct ospf_lsdb *new;
XFREE(MTYPE_OSPF_PACKET, op);
}
-struct ospf_fifo *ospf_fifo_new()
+struct ospf_fifo *ospf_fifo_new(void)
{
struct ospf_fifo *new;
return rc;
}
-static int ospf_router_info_unregister()
+static int ospf_router_info_unregister(void)
{
if ((OspfRI.scope != OSPF_OPAQUE_AS_LSA)
#include "ospfd/ospf_zebra.h"
#include "ospfd/ospf_dump.h"
-struct ospf_route *ospf_route_new()
+struct ospf_route *ospf_route_new(void)
{
struct ospf_route *new;
return new;
}
-void ospf_route_free(struct ospf_route * or)
+void ospf_route_free(struct ospf_route *or)
{
if (or->paths)
list_delete(& or->paths);
XFREE(MTYPE_OSPF_ROUTE, or);
}
-struct ospf_path *ospf_path_new()
+struct ospf_path *ospf_path_new(void)
{
struct ospf_path *new;
return rc;
}
-static int ospf_mpls_te_unregister()
+static int ospf_mpls_te_unregister(void)
{
uint8_t scope;
* Signal handlers
*/
-static void pim_sighup()
+static void pim_sighup(void)
{
zlog_info("SIGHUP received, ignoring");
}
-static void pim_sigint()
+static void pim_sigint(void)
{
zlog_notice("Terminating on signal SIGINT");
pim_terminate();
exit(1);
}
-static void pim_sigterm()
+static void pim_sigterm(void)
{
zlog_notice("Terminating on signal SIGTERM");
pim_terminate();
exit(1);
}
-static void pim_sigusr1()
+static void pim_sigusr1(void)
{
zlog_rotate();
}
XFREE(MTYPE_PIM_STATIC_ROUTE, s_route);
}
-static struct static_route *static_route_alloc()
+static struct static_route *static_route_alloc(void)
{
return XCALLOC(MTYPE_PIM_STATIC_ROUTE, sizeof(struct static_route));
}
-static struct static_route *static_route_new(unsigned int iif, unsigned int oif,
+static struct static_route *static_route_new(ifindex_t iif, ifindex_t oif,
struct in_addr group,
struct in_addr source)
{
ifindex_t iif_index = pim_iif ? pim_iif->mroute_vif_index : 0;
ifindex_t oif_index = pim_oif ? pim_oif->mroute_vif_index : 0;
- if (!iif_index || !oif_index) {
+ if (!iif_index || !oif_index || iif_index == -1 || oif_index == -1) {
zlog_warn(
"%s %s: Unable to add static route: Invalid interface index(iif=%d,oif=%d)",
__FILE__, __PRETTY_FUNCTION__, iif_index, oif_index);
pim_time_monotonic_sec():
number of seconds since some unspecified starting point
*/
-int64_t pim_time_monotonic_sec()
+int64_t pim_time_monotonic_sec(void)
{
struct timeval now_tv;
pim_time_monotonic_dsec():
number of deciseconds since some unspecified starting point
*/
-int64_t pim_time_monotonic_dsec()
+int64_t pim_time_monotonic_dsec(void)
{
struct timeval now_tv;
int64_t now_dsec;
}
}
-static void pim_free()
+static void pim_free(void)
{
pim_route_map_terminate();
pim_cmd_init();
}
-void pim_terminate()
+void pim_terminate(void)
{
struct zclient *zclient;
}
/* Needed for stop RIP process. */
-void rip_if_down_all()
+void rip_if_down_all(void)
{
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
}
/* Apply network configuration to all interface. */
-void rip_enable_apply_all()
+void rip_enable_apply_all(void)
{
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
}
/* Clear all network and neighbor configuration. */
-void rip_clean_network()
+void rip_clean_network(void)
{
unsigned int i;
char *str;
return strcmp(o1->ifname, o2->ifname);
}
-void rip_offset_init()
+void rip_offset_init(void)
{
rip_offset_list_master = list_new();
rip_offset_list_master->cmp = (int (*)(void *, void *))offset_list_cmp;
rip_offset_list_master->del = (void (*)(void *))offset_list_del;
}
-void rip_offset_clean()
+void rip_offset_clean(void)
{
list_delete(&rip_offset_list_master);
#define SET_STR "Set values in destination routing protocol\n"
/* Route-map init */
-void rip_route_map_init()
+void rip_route_map_init(void)
{
route_map_init();
return write;
}
-void ripng_debug_init()
+void ripng_debug_init(void)
{
ripng_debug_event = 0;
ripng_debug_packet = 0;
}
/* Clear all network and neighbor configuration */
-void ripng_clean_network()
+void ripng_clean_network(void)
{
unsigned int i;
char *str;
};
/* Initialization of interface. */
-void ripng_if_init()
+void ripng_if_init(void)
{
/* Interface initialize. */
hook_register_prio(if_add, 0, ripng_if_new_hook);
return memcmp(&p1->addr, &p2->addr, sizeof(struct in6_addr));
}
-void ripng_peer_init()
+void ripng_peer_init(void)
{
peer_list = list_new();
peer_list->cmp = (int (*)(void *, void *))ripng_peer_list_cmp;
#define MATCH_STR "Match values from routing table\n"
#define SET_STR "Set values in destination routing protocol\n"
-void ripng_route_map_init()
+void ripng_route_map_init(void)
{
route_map_init();
return vrf_bitmap_check(zclient->redist[AFI_IP6][type], VRF_DEFAULT);
}
-void ripng_redistribute_clean()
+void ripng_redistribute_clean(void)
{
for (int i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (!vrf_bitmap_check(zclient->redist[AFI_IP6][i], VRF_DEFAULT))
}
/* Allocate new ripng information. */
-struct ripng_info *ripng_info_new()
+struct ripng_info *ripng_info_new(void)
{
struct ripng_info *new;
}
/* delete all the added ripng routes. */
-void ripng_clean()
+void ripng_clean(void)
{
int i;
struct agg_node *rp;
}
/* Initialize ripng structure and set commands. */
-void ripng_init()
+void ripng_init(void)
{
/* Install RIPNG_NODE. */
install_node(&cmd_ripng_node, ripng_config_write);
return fails;
}
-static void empty_get_test()
+static void empty_get_test(void)
{
struct aspath *as = aspath_empty_get();
struct test_spec sp = {"", "", 0, 0, 0, 0, 0, 0};
}
/* cmp_left tests */
-static void cmp_test()
+static void cmp_test(void)
{
unsigned int i;
#define CMP_TESTS_MAX (sizeof(left_compare) / sizeof(struct compare_tests))
TestFlag.okfail('peer\\advertisement-interval')
TestFlag.okfail('peer\\capability dynamic')
TestFlag.okfail('peer\\capability extended-nexthop')
-TestFlag.okfail('peer\\capability extended-nexthop')
+#TestFlag.okfail('peer\\capability extended-nexthop')
TestFlag.okfail('peer\\description')
TestFlag.okfail('peer\\disable-connected-check')
TestFlag.okfail('peer\\dont-capability-negotiate')
#include "memory.h"
#include "memory_vty.h"
-extern void test_init();
+extern void test_init(void);
struct thread_master *master;
return 0;
}
-static void test_timer_init()
+static void test_timer_init(void)
{
thread_add_timer(master, test_timer, &timer_count, 10, NULL);
}
-static void test_vty_init()
+static void test_vty_init(void)
{
install_element(VIEW_NODE, &daemon_exit_cmd);
}
return CMD_SUCCESS;
}
-static void slow_vty_init()
+static void slow_vty_init(void)
{
install_element(VIEW_NODE, &clear_foo_cmd);
}
-void test_init()
+void test_init(void)
{
slow_vty_init();
}
return CMD_SUCCESS;
}
-void test_init()
+void test_init(void)
{
install_element(VIEW_NODE, &clear_foo_cmd);
}
return CMD_SUCCESS;
}
-static int heavy_wq_init()
+static int heavy_wq_init(void)
{
heavy_wq = work_queue_new(master, "heavy_work_queue");
return 0;
}
-void test_init()
+void test_init(void)
{
install_element(VIEW_NODE, &clear_foo_cmd);
heavy_wq_init();
*
* Tests comparision of prefixes according to order of iteration.
*/
-static void test_prefix_iter_cmp()
+static void test_prefix_iter_cmp(void)
{
printf("\n\nTesting route_table_prefix_iter_cmp()\n");
#endif
#ifdef HAVE_LXC
-static void set_namespaces()
+static void set_namespaces(void)
{
struct namespace *namespace;
int fd;
}
}
#else
-static void set_namespaces()
+static void set_namespaces(void)
{
if (!LIST_EMPTY(&namespace_head))
fatal("LCX namespaces not supported");
# Output install_element
print <<EOF;
-void
-vtysh_init_cmd ()
+void vtysh_init_cmd(void)
{
EOF
.completions = vtysh_autocomplete},
{.completions = NULL}};
-void vtysh_uninit()
+void vtysh_uninit(void)
{
if (vty->of != stdout)
fclose(vty->of);
* be edited by hand. So, we handle only "write terminal" case here and
* integrate vtysh specific conf with conf from daemons.
*/
-void vtysh_config_write()
+void vtysh_config_write(void)
{
char line[81];
user_config_write();
}
-void vtysh_config_init()
+void vtysh_config_init(void)
{
config_top = list_new();
config_top->del = (void (*)(void *))line_del;
return NULL;
}
-void user_config_write()
+void user_config_write(void)
{
struct listnode *node, *nnode;
struct vtysh_user *user;
#
# libyang user types
#
+
+if LIBYANG_EXT_BUILTIN
+lib_libfrr_la_SOURCES += yang/libyang_plugins/frr_user_types.c
+else
libyang_plugins_LTLIBRARIES += yang/libyang_plugins/frr_user_types.la
+endif
yang_libyang_plugins_frr_user_types_la_CFLAGS = $(WERROR)
yang_libyang_plugins_frr_user_types_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
.ifindex = ifp->ifindex,
.vrf_id = ifp->vrf_id,
};
+ uint32_t metric;
if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
return;
break;
}
+ metric = (ifc->metric < (uint32_t)METRIC_MAX) ?
+ ifc->metric : ifp->metric;
rib_add(afi, SAFI_UNICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, &p,
- NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
+ NULL, &nh, RT_TABLE_MAIN, metric, 0, 0, 0);
rib_add(afi, SAFI_MULTICAST, ifp->vrf_id, ZEBRA_ROUTE_CONNECT, 0, 0, &p,
- NULL, &nh, RT_TABLE_MAIN, ifp->metric, 0, 0, 0);
+ NULL, &nh, RT_TABLE_MAIN, metric, 0, 0, 0);
if (IS_ZEBRA_DEBUG_RIB_DETAILED) {
char buf[PREFIX_STRLEN];
/* Add connected IPv4 route to the interface. */
void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
uint16_t prefixlen, struct in_addr *broad,
- const char *label)
+ const char *label, uint32_t metric)
{
struct prefix_ipv4 *p;
struct connected *ifc;
ifc = connected_new();
ifc->ifp = ifp;
ifc->flags = flags;
+ ifc->metric = metric;
/* If we get a notification from the kernel,
* we can safely assume the address is known to the kernel */
SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
/* Add connected IPv6 route to the interface. */
void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
struct in6_addr *broad, uint16_t prefixlen,
- const char *label)
+ const char *label, uint32_t metric)
{
struct prefix_ipv6 *p;
struct connected *ifc;
ifc = connected_new();
ifc->ifp = ifp;
ifc->flags = flags;
+ ifc->metric = metric;
/* If we get a notification from the kernel,
* we can safely assume the address is known to the kernel */
SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
extern void connected_add_ipv4(struct interface *ifp, int flags,
struct in_addr *addr, uint16_t prefixlen,
- struct in_addr *broad, const char *label);
+ struct in_addr *broad, const char *label,
+ uint32_t metric);
extern void connected_delete_ipv4(struct interface *ifp, int flags,
struct in_addr *addr, uint16_t prefixlen,
extern void connected_add_ipv6(struct interface *ifp, int flags,
struct in6_addr *address, struct in6_addr *broad,
- uint16_t prefixlen, const char *label);
+ uint16_t prefixlen, const char *label,
+ uint32_t metric);
extern void connected_delete_ipv6(struct interface *ifp,
struct in6_addr *address,
struct in6_addr *broad, uint16_t prefixlen);
}
connected_add_ipv4(ifp, flags, &addr->sin_addr,
- prefixlen, dest_pnt, NULL);
+ prefixlen, dest_pnt, NULL,
+ METRIC_MAX);
}
if (ifap->ifa_addr->sa_family == AF_INET6) {
struct sockaddr_in6 *addr;
#endif
connected_add_ipv6(ifp, flags, &addr->sin6_addr, NULL,
- prefixlen, NULL);
+ prefixlen, NULL, METRIC_MAX);
}
}
/* Set address to the interface. */
if (af == AF_INET)
connected_add_ipv4(ifp, flags, &SIN(addr)->sin_addr, prefixlen,
- (struct in_addr *)dest_pnt, label);
+ (struct in_addr *)dest_pnt, label,
+ METRIC_MAX);
else if (af == AF_INET6)
connected_add_ipv6(ifp, flags, &SIN6(addr)->sin6_addr, NULL,
- prefixlen, label);
+ prefixlen, label, METRIC_MAX);
return 0;
}
uint8_t flags = 0;
char *label = NULL;
struct zebra_ns *zns;
+ uint32_t metric = METRIC_MAX;
zns = zebra_ns_lookup(ns_id);
ifa = NLMSG_DATA(h);
if (label && strcmp(ifp->name, label) == 0)
label = NULL;
+ if (tb[IFA_RT_PRIORITY])
+ metric = *(uint32_t *)RTA_DATA(tb[IFA_RT_PRIORITY]);
+
/* Register interface address to the interface. */
if (ifa->ifa_family == AF_INET) {
if (ifa->ifa_prefixlen > IPV4_MAX_BITLEN) {
if (h->nlmsg_type == RTM_NEWADDR)
connected_add_ipv4(ifp, flags, (struct in_addr *)addr,
ifa->ifa_prefixlen,
- (struct in_addr *)broad, label);
+ (struct in_addr *)broad, label,
+ metric);
else
connected_delete_ipv4(
ifp, flags, (struct in_addr *)addr,
connected_add_ipv6(ifp, flags,
(struct in6_addr *)addr,
(struct in6_addr *)broad,
- ifa->ifa_prefixlen, label);
+ ifa->ifa_prefixlen, label,
+ metric);
} else
connected_delete_ipv6(ifp, (struct in6_addr *)addr,
(struct in6_addr *)broad,
return CMD_SUCCESS;
}
-void irdp_if_init()
+void irdp_if_init(void)
{
hook_register(zebra_if_config_wr, irdp_config_write);
hook_register(if_del, irdp_if_delete);
connected_add_ipv4(ifp, flags, &addr.sin.sin_addr,
ip_masklen(mask.sin.sin_addr),
&brd.sin.sin_addr,
- (isalias ? ifname : NULL));
+ (isalias ? ifname : NULL),
+ METRIC_MAX);
else
connected_delete_ipv4(ifp, flags, &addr.sin.sin_addr,
ip_masklen(mask.sin.sin_addr),
connected_add_ipv6(ifp, flags, &addr.sin6.sin6_addr,
NULL,
ip6_masklen(mask.sin6.sin6_addr),
- (isalias ? ifname : NULL));
+ (isalias ? ifname : NULL),
+ METRIC_MAX);
else
connected_delete_ipv6(ifp, &addr.sin6.sin6_addr, NULL,
ip6_masklen(mask.sin6.sin6_addr));
}
-void label_manager_close()
+void label_manager_close(void)
{
list_delete(&lbl_mgr.lc_list);
stream_free(obuf);
*/
if (cmd != RTM_ADD && cmd != RTM_DELETE) {
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("%s: %s odd command %s for flags %d",
+ zlog_debug("%s: %s odd command %s",
__func__, prefix_buf,
- lookup_msg(rtm_type_str, cmd, NULL),
- nexthop->flags);
+ lookup_msg(rtm_type_str, cmd, NULL));
return 0;
}
if (dplane_ctx_get_src(ctx) != NULL) {
zlog_err("route add: IPv6 sourcedest routes unsupported!");
- res = ZEBRA_DPLANE_REQUEST_FAILURE;
- goto done;
+ return ZEBRA_DPLANE_REQUEST_FAILURE;
}
frr_elevate_privs(&zserv_privs) {
}
} /* Elevated privs */
-done:
-
return res;
}
#include "lib/memory.h"
#include "lib/queue.h"
#include "lib/zebra.h"
+#include "zebra/zebra_router.h"
#include "zebra/zebra_memory.h"
#include "zebra/zserv.h"
#include "zebra/zebra_dplane.h"
/* Trying out the sequence number idea, so we can try to detect
* when a result is stale.
*/
- re->dplane_sequence++;
+ re->dplane_sequence = zebra_router_get_next_sequence();
ctx->zd_seq = re->dplane_sequence;
ret = AOK;
old_re && (old_re != re)) {
ctx->zd_is_update = true;
- old_re->dplane_sequence++;
+ old_re->dplane_sequence =
+ zebra_router_get_next_sequence();
ctx->zd_old_seq = old_re->dplane_sequence;
ctx->u.rinfo.zd_old_tag = old_re->tag;
if ((cmd == RTM_NEWROUTE
&& CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
|| (cmd == RTM_DELROUTE
- && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))) {
+ && CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED))) {
netlink_route_info_add_nh(ri, nexthop);
}
}
} else if (CHECK_FLAG(re->flags, ZEBRA_FLAG_ALLOW_RECURSION)) {
resolved = 0;
for (ALL_NEXTHOPS(match->ng, newhop)) {
- if (!CHECK_FLAG(newhop->flags,
- NEXTHOP_FLAG_FIB))
+ if (!CHECK_FLAG(match->status,
+ ROUTE_ENTRY_INSTALLED))
continue;
if (CHECK_FLAG(newhop->flags,
NEXTHOP_FLAG_RECURSIVE))
} else if (re->type == ZEBRA_ROUTE_STATIC) {
resolved = 0;
for (ALL_NEXTHOPS(match->ng, newhop)) {
- if (!CHECK_FLAG(newhop->flags,
- NEXTHOP_FLAG_FIB))
+ if (!CHECK_FLAG(match->status,
+ ROUTE_ENTRY_INSTALLED))
continue;
if (set) {
struct route_table *table;
struct route_node *rn;
struct route_entry *match = NULL;
- struct nexthop *newhop;
/* Lookup table. */
table = zebra_vrf_table(afi, safi, vrf_id);
route_lock_node(rn);
} else {
if (match->type != ZEBRA_ROUTE_CONNECT) {
- int found = 0;
- for (ALL_NEXTHOPS(match->ng, newhop))
- if (CHECK_FLAG(newhop->flags,
- NEXTHOP_FLAG_FIB)) {
- found = 1;
- break;
- }
- if (!found)
+ if (!CHECK_FLAG(match->status,
+ ROUTE_ENTRY_INSTALLED))
return NULL;
}
struct route_table *table;
struct route_node *rn;
struct route_entry *match = NULL;
- struct nexthop *nexthop;
rib_dest_t *dest;
/* Lookup table. */
if (match->type == ZEBRA_ROUTE_CONNECT)
return match;
- for (ALL_NEXTHOPS(match->ng, nexthop))
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
- return match;
+ if (CHECK_FLAG(match->status, ROUTE_ENTRY_INSTALLED))
+ return match;
return NULL;
}
switch (ret) {
case ZEBRA_DPLANE_REQUEST_QUEUED:
+ SET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
+ if (old)
+ SET_FLAG(old->status, ROUTE_ENTRY_QUEUED);
if (zvrf)
zvrf->installs_queued++;
break;
struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id);
if (info->safi != SAFI_UNICAST) {
+ UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
for (ALL_NEXTHOPS(re->ng, nexthop))
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
return;
if (!RIB_SYSTEM_ROUTE(re))
rib_uninstall_kernel(rn, re);
+ else
+ UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
dest->selected_fib = NULL;
if (!RIB_SYSTEM_ROUTE(old))
rib_uninstall_kernel(rn, old);
else {
+ UNSET_FLAG(old->status, ROUTE_ENTRY_INSTALLED);
/*
* We are setting this to NULL here
* because that is what we traditionally
rib_install_kernel(rn, new, old);
} else {
+ UNSET_FLAG(new->status, ROUTE_ENTRY_INSTALLED);
/*
* We do not need to install the
* selected route because it
if (RIB_SYSTEM_ROUTE(new)) {
if (!RIB_SYSTEM_ROUTE(old))
rib_uninstall_kernel(rn, old);
+ else
+ UNSET_FLAG(
+ old->status,
+ ROUTE_ENTRY_INSTALLED);
} else {
+ UNSET_FLAG(old->status,
+ ROUTE_ENTRY_INSTALLED);
for (nexthop = old->ng.nexthop; nexthop;
nexthop = nexthop->next)
UNSET_FLAG(nexthop->flags,
if (!RIB_SYSTEM_ROUTE(old))
rib_uninstall_kernel(rn, old);
- else
+ else {
+ UNSET_FLAG(old->status, ROUTE_ENTRY_INSTALLED);
dest->selected_fib = NULL;
+ }
}
} else {
/*
* is ready
* to add routes.
*/
- if (!RIB_SYSTEM_ROUTE(new)) {
- bool in_fib = false;
-
- for (ALL_NEXTHOPS(new->ng, nexthop))
- if (CHECK_FLAG(nexthop->flags,
- NEXTHOP_FLAG_FIB)) {
- in_fib = true;
- break;
- }
- if (!in_fib)
- rib_install_kernel(rn, new, NULL);
- }
+ if (!RIB_SYSTEM_ROUTE(new)
+ && !CHECK_FLAG(new->status, ROUTE_ENTRY_INSTALLED))
+ rib_install_kernel(rn, new, NULL);
}
/* Update prior route. */
/*
* Check sequence number(s) to detect stale results before continuing
*/
- if (re && (re->dplane_sequence != dplane_ctx_get_seq(ctx))) {
- if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
- zlog_debug("%u:%s Stale dplane result for re %p",
- dplane_ctx_get_vrf(ctx), dest_str, re);
- }
- re = NULL;
- }
-
- if (old_re &&
- (old_re->dplane_sequence != dplane_ctx_get_old_seq(ctx))) {
- if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
- zlog_debug("%u:%s Stale dplane result for old_re %p",
- dplane_ctx_get_vrf(ctx), dest_str, old_re);
- }
- old_re = NULL;
- }
-
- /*
- * Here's sort of a tough one: the route update result is stale.
- * Is it better to use the context block info to generate
- * redist and owner notification, or is it better to wait
- * for the up-to-date result to arrive?
- */
- if (re == NULL) {
- /* TODO -- for now, only expose up-to-date results */
- goto done;
+ if (re) {
+ if (re->dplane_sequence != dplane_ctx_get_seq(ctx)) {
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
+ zlog_debug("%u:%s Stale dplane result for re %p",
+ dplane_ctx_get_vrf(ctx),
+ dest_str, re);
+ } else
+ UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
+ }
+
+ if (old_re) {
+ if (old_re->dplane_sequence != dplane_ctx_get_old_seq(ctx)) {
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
+ zlog_debug("%u:%s Stale dplane result for old_re %p",
+ dplane_ctx_get_vrf(ctx),
+ dest_str, old_re);
+ } else
+ UNSET_FLAG(re->status, ROUTE_ENTRY_QUEUED);
}
switch (op) {
case DPLANE_OP_ROUTE_INSTALL:
case DPLANE_OP_ROUTE_UPDATE:
if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) {
+ if (re) {
+ UNSET_FLAG(re->status, ROUTE_ENTRY_FAILED);
+ SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
+ }
+ if (old_re) {
+ UNSET_FLAG(old_re->status, ROUTE_ENTRY_FAILED);
+ UNSET_FLAG(old_re->status,
+ ROUTE_ENTRY_INSTALLED);
+ }
/* Update zebra nexthop FIB flag for each
* nexthop that was installed.
*/
for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx),
ctx_nexthop)) {
+ if (!re)
+ continue;
+
for (ALL_NEXTHOPS(re->ng, nexthop)) {
if (nexthop_same(ctx_nexthop, nexthop))
break;
* 'old' context info was stale, 'old_re' will be
* NULL here and that delete will not be sent.
*/
- redistribute_update(dest_pfx, src_pfx, re, old_re);
+ if (re)
+ redistribute_update(dest_pfx, src_pfx,
+ re, old_re);
/* Notify route owner */
- zsend_route_notify_owner(re, dest_pfx,
- ZAPI_ROUTE_INSTALLED);
+ zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_INSTALLED);
} else {
- zsend_route_notify_owner(re, dest_pfx,
- ZAPI_ROUTE_FAIL_INSTALL);
+ if (re)
+ SET_FLAG(re->status, ROUTE_ENTRY_FAILED);
+ if (old_re)
+ SET_FLAG(old_re->status, ROUTE_ENTRY_FAILED);
+ if (re)
+ zsend_route_notify_owner(re, dest_pfx,
+ ZAPI_ROUTE_FAIL_INSTALL);
zlog_warn("%u:%s: Route install failed",
dplane_ctx_get_vrf(ctx),
}
break;
case DPLANE_OP_ROUTE_DELETE:
+ if (re)
+ SET_FLAG(re->status, ROUTE_ENTRY_FAILED);
/*
* In the delete case, the zebra core datastructs were
* updated (or removed) at the time the delete was issued,
* so we're just notifying the route owner.
*/
if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) {
+ if (re) {
+ UNSET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
+ UNSET_FLAG(re->status, ROUTE_ENTRY_FAILED);
+ }
zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_REMOVED);
if (zvrf)
zvrf->removals++;
} else {
+ if (re)
+ SET_FLAG(re->status, ROUTE_ENTRY_FAILED);
zsend_route_notify_owner_ctx(ctx,
ZAPI_ROUTE_REMOVE_FAIL);
(CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)
? "ACTIVE "
: ""),
- (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
+ (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)
? "FIB "
: ""),
(CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)
}
/* If this route is kernel route, set FIB flag to the route. */
- if (RIB_SYSTEM_ROUTE(re))
+ if (RIB_SYSTEM_ROUTE(re)) {
+ SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next)
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
+ }
/* Link new re to node.*/
if (IS_ZEBRA_DEBUG_RIB) {
rn, fib, fib->type);
}
if (allow_delete) {
+ UNSET_FLAG(fib->status, ROUTE_ENTRY_INSTALLED);
/* Unset flags. */
for (rtnh = fib->ng.nexthop; rtnh;
rtnh = rtnh->next)
* to a different spot (ie startup )
* this decision needs to be revisited
*/
+ SET_FLAG(re->status, ROUTE_ENTRY_INSTALLED);
for (ALL_NEXTHOPS(re->ng, nexthop))
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
struct zserv *client;
char bufn[INET6_ADDRSTRLEN];
struct listnode *node;
- struct nexthop *nexthop;
if (re && (rnh->state == NULL)) {
- for (ALL_NEXTHOPS(re->ng, nexthop))
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) {
- state_changed = 1;
- break;
- }
+ if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED))
+ state_changed = 1;
} else if (!re && (rnh->state != NULL))
state_changed = 1;
* check in a couple of places, so this is a single home for the logic we
* use.
*/
-static bool rnh_nexthop_valid(const struct nexthop *nh)
+static bool rnh_nexthop_valid(const struct route_entry *re,
+ const struct nexthop *nh)
{
- return (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_FIB)
+ return (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)
&& CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ACTIVE));
}
* have an installed nexthop to be useful.
*/
for (ALL_NEXTHOPS(re->ng, nexthop)) {
- if (rnh_nexthop_valid(nexthop))
+ if (rnh_nexthop_valid(re, nexthop))
break;
}
state->distance = re->distance;
state->metric = re->metric;
state->vrf_id = re->vrf_id;
+ state->status = re->status;
route_entry_copy_nexthops(state, re->ng.nexthop);
rnh->state = state;
nump = stream_get_endp(s);
stream_putc(s, 0);
for (ALL_NEXTHOPS(re->ng, nh))
- if (rnh_nexthop_valid(nh)) {
+ if (rnh_nexthop_valid(re, nh)) {
stream_putl(s, nh->vrf_id);
stream_putc(s, nh->type);
switch (nh->type) {
zebra_rmap_update_timer);
}
-void zebra_route_map_init()
+void zebra_route_map_init(void)
{
install_element(CONFIG_NODE, &ip_protocol_cmd);
install_element(CONFIG_NODE, &no_ip_protocol_cmd);
*/
#include "zebra.h"
+#include <pthread.h>
+#include "lib/frratomic.h"
+
#include "zebra_router.h"
#include "zebra_memory.h"
#include "zebra_pbr.h"
XFREE(MTYPE_ZEBRA_NS, zrt);
}
+uint32_t zebra_router_get_next_sequence(void)
+{
+ return 1
+ + atomic_fetch_add_explicit(&zrouter.sequence_num, 1,
+ memory_order_relaxed);
+}
+
void zebra_router_terminate(void)
{
struct zebra_router_table *zrt, *tmp;
void zebra_router_init(void)
{
+ zrouter.sequence_num = 0;
+
zebra_vxlan_init();
zebra_mlag_init();
#if defined(HAVE_RTADV)
struct rtadv rtadv;
#endif /* HAVE_RTADV */
+
+ /* A sequence number used for tracking routes */
+ _Atomic uint32_t sequence_num;
};
extern struct zebra_router zrouter;
extern void zebra_router_sweep_route(void);
extern void zebra_router_show_table_summary(struct vty *vty);
+
+extern uint32_t zebra_router_get_next_sequence(void);
#endif
return CMD_SUCCESS;
}
+static char re_status_output_char(struct route_entry *re, struct nexthop *nhop)
+{
+ if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) {
+ if (!CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_DUPLICATE))
+ return '*';
+ else
+ return ' ';
+ }
+
+ if (CHECK_FLAG(re->status, ROUTE_ENTRY_FAILED)) {
+ if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
+ return 'q';
+
+ return 'f';
+ }
+
+ if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
+ return 'q';
+
+ return ' ';
+}
+
/* New RIB. Detailed information for IPv4 route. */
static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
int mcast)
char addrstr[32];
vty_out(vty, " %c%s",
- CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
- ? CHECK_FLAG(nexthop->flags,
- NEXTHOP_FLAG_DUPLICATE)
- ? ' '
- : '*'
- : ' ',
+ re_status_output_char(re, nexthop),
nexthop->rparent ? " " : "");
switch (nexthop->type) {
if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED))
json_object_boolean_true_add(json_route, "selected");
+ json_object_int_add(json_route, "distance",
+ re->distance);
+ json_object_int_add(json_route, "metric", re->metric);
+
+ if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED))
+ json_object_boolean_true_add(json_route, "installed");
+
+ if (CHECK_FLAG(re->status, ROUTE_ENTRY_FAILED))
+ json_object_boolean_true_add(json_route, "failed");
+
+ if (CHECK_FLAG(re->status, ROUTE_ENTRY_QUEUED))
+ json_object_boolean_true_add(json_route, "queued");
+
if (re->type != ZEBRA_ROUTE_CONNECT) {
json_object_int_add(json_route, "distance",
re->distance);
CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)
? '>'
: ' ',
- CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
- ? '*'
- : ' ',
+ re_status_output_char(re, nexthop),
srcdest_rnode2str(rn, buf, sizeof buf));
/* Distance and metric display. */
- if (re->type != ZEBRA_ROUTE_CONNECT)
+ if (((re->type == ZEBRA_ROUTE_CONNECT) &&
+ (re->distance || re->metric)) ||
+ (re->type != ZEBRA_ROUTE_CONNECT))
len += vty_out(vty, " [%u/%u]", re->distance,
re->metric);
} else {
vty_out(vty, " %c%*c",
- CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)
- ? CHECK_FLAG(nexthop->flags,
- NEXTHOP_FLAG_DUPLICATE)
- ? ' '
- : '*'
- : ' ',
+ re_status_output_char(re, nexthop),
len - 3 + (2 * nexthop_level(nexthop)), ' ');
}
* In case of ECMP, count only once.
*/
cnt = 0;
+ if (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)) {
+ fib_cnt[ZEBRA_ROUTE_TOTAL]++;
+ fib_cnt[re->type]++;
+ }
for (nexthop = re->ng.nexthop; (!cnt && nexthop);
nexthop = nexthop->next) {
cnt++;
rib_cnt[ZEBRA_ROUTE_TOTAL]++;
rib_cnt[re->type]++;
- if (CHECK_FLAG(nexthop->flags,
- NEXTHOP_FLAG_FIB)) {
- fib_cnt[ZEBRA_ROUTE_TOTAL]++;
- fib_cnt[re->type]++;
- }
if (re->type == ZEBRA_ROUTE_BGP
&& CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP)) {
rib_cnt[ZEBRA_ROUTE_IBGP]++;
- if (CHECK_FLAG(nexthop->flags,
- NEXTHOP_FLAG_FIB))
+ if (CHECK_FLAG(re->status,
+ ROUTE_ENTRY_INSTALLED))
fib_cnt[ZEBRA_ROUTE_IBGP]++;
}
}
static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
struct ipaddr *ip, uint8_t flags,
- uint32_t seq, uint16_t cmd);
+ uint32_t seq, int state, uint16_t cmd);
static unsigned int neigh_hash_keymake(void *p);
static void *zvni_neigh_alloc(void *p);
static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip,
uint8_t flags, uint32_t seq);
static int zvni_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip,
struct ethaddr *macaddr,
- uint8_t flags);
+ uint8_t flags, int state);
static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n);
static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n);
static zebra_vni_t *zvni_from_svi(struct interface *ifp,
static int zvni_del(zebra_vni_t *zvni);
static int zvni_send_add_to_client(zebra_vni_t *zvni);
static int zvni_send_del_to_client(vni_t vni);
-static void zvni_build_hash_table();
+static void zvni_build_hash_table(void);
static int zvni_vtep_match(struct in_addr *vtep_ip, zebra_vtep_t *zvtep);
static zebra_vtep_t *zvni_vtep_find(zebra_vni_t *zvni, struct in_addr *vtep_ip);
static zebra_vtep_t *zvni_vtep_add(zebra_vni_t *zvni, struct in_addr *vtep_ip);
*/
static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
struct ipaddr *ip, uint8_t flags,
- uint32_t seq, uint16_t cmd)
+ uint32_t seq, int state, uint16_t cmd)
{
char buf[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN];
if (cmd == ZEBRA_MACIP_ADD) {
stream_putc(s, flags); /* sticky mac/gateway mac */
stream_putl(s, seq); /* sequence number */
+ } else {
+ stream_putl(s, state); /* state - active/inactive */
}
&& IPV4_ADDR_SAME(&n->r_vtep_ip, &wctx->r_vtep_ip))) {
if (wctx->upd_client && (n->flags & ZEBRA_NEIGH_LOCAL))
zvni_neigh_send_del_to_client(wctx->zvni->vni, &n->ip,
- &n->emac, 0);
+ &n->emac, 0, n->state);
if (wctx->uninstall)
zvni_neigh_uninstall(wctx->zvni, n);
ZEBRA_NEIGH_SET_INACTIVE(n);
n->loc_seq = 0;
zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
- &n->emac, 0);
+ &n->emac, 0, ZEBRA_NEIGH_ACTIVE);
}
}
}
ZEBRA_NEIGH_SET_INACTIVE(n);
n->loc_seq = 0;
zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
- &n->emac, 0);
+ &n->emac, 0, ZEBRA_NEIGH_ACTIVE);
}
}
}
SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags,
- seq, ZEBRA_MACIP_ADD);
+ seq, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_ADD);
}
/*
* Inform BGP about local neighbor deletion.
*/
static int zvni_neigh_send_del_to_client(vni_t vni, struct ipaddr *ip,
- struct ethaddr *macaddr, uint8_t flags)
+ struct ethaddr *macaddr, uint8_t flags,
+ int state)
{
return zvni_macip_send_msg_to_client(vni, macaddr, ip, flags,
- 0, ZEBRA_MACIP_DEL);
+ 0, state, ZEBRA_MACIP_DEL);
}
/*
/* Remove neighbor from BGP. */
zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac,
- ZEBRA_MACIP_TYPE_GW);
+ ZEBRA_MACIP_TYPE_GW, ZEBRA_NEIGH_ACTIVE);
/* Delete this neighbor entry. */
zvni_neigh_del(zvni, n);
*/
if (IS_ZEBRA_NEIGH_ACTIVE(n))
zvni_neigh_send_del_to_client(zvni->vni, &n->ip,
- &n->emac, 0);
+ &n->emac, 0, n->state);
old_zmac = zvni_mac_lookup(zvni, &n->emac);
if (old_zmac) {
old_mac_seq = CHECK_FLAG(old_zmac->flags,
SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
return zvni_macip_send_msg_to_client(vni, macaddr, NULL, flags,
- seq, ZEBRA_MACIP_ADD);
+ seq, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_ADD);
}
/*
static int zvni_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr)
{
return zvni_macip_send_msg_to_client(vni, macaddr, NULL, 0 /* flags */,
- 0 /* seq */, ZEBRA_MACIP_DEL);
+ 0 /* seq */, ZEBRA_NEIGH_ACTIVE, ZEBRA_MACIP_DEL);
}
/*
* Build the VNI hash table by going over the VxLAN interfaces. This
* is called when EVPN (advertise-all-vni) is enabled.
*/
-static void zvni_build_hash_table()
+static void zvni_build_hash_table(void)
{
struct zebra_ns *zns;
struct route_node *rn;
IS_ZEBRA_NEIGH_ACTIVE(n))
zvni_neigh_send_del_to_client(
zvni->vni, &n->ip,
- &n->emac, 0);
+ &n->emac, 0, n->state);
/* update neigh list for macs */
old_mac = zvni_mac_lookup(zvni, &n->emac);
}
/* Remove neighbor from BGP. */
- if (IS_ZEBRA_NEIGH_ACTIVE(n))
- zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac, 0);
+ zvni_neigh_send_del_to_client(zvni->vni, &n->ip, &n->emac,
+ 0, n->state);
/* Delete this neighbor entry. */
zvni_neigh_del(zvni, n);
/* Is EVPN enabled? */
#define EVPN_ENABLED(zvrf) (zvrf)->advertise_all_vni
-static inline int is_evpn_enabled()
+static inline int is_evpn_enabled(void)
{
struct zebra_vrf *zvrf = NULL;
zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
}
static inline int
-is_vxlan_flooding_head_end()
+is_vxlan_flooding_head_end(void)
{
struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT);
struct json_object *json;
};
-enum zebra_neigh_state { ZEBRA_NEIGH_INACTIVE = 0, ZEBRA_NEIGH_ACTIVE = 1 };
+#define IS_ZEBRA_NEIGH_ACTIVE(n) (n->state == ZEBRA_NEIGH_ACTIVE)
-#define IS_ZEBRA_NEIGH_ACTIVE(n) n->state == ZEBRA_NEIGH_ACTIVE
-
-#define IS_ZEBRA_NEIGH_INACTIVE(n) n->state == ZEBRA_NEIGH_INACTIVE
+#define IS_ZEBRA_NEIGH_INACTIVE(n) (n->state == ZEBRA_NEIGH_INACTIVE)
#define ZEBRA_NEIGH_SET_ACTIVE(n) n->state = ZEBRA_NEIGH_ACTIVE