/conftest.err
/aclocal.m4
/libtool
+/libtool.orig
/Makefile
/Makefile.in
void babelz_zebra_init(void)
{
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_BABEL, 0, &babeld_privs);
zclient->zebra_connected = babel_zebra_connected;
if (bpc->bpc_has_localif) {
STREAM_GET(bpc->bpc_localif, msg, ifnamelen);
bpc->bpc_localif[ifnamelen] = 0;
+
+ /*
+ * IPv6 link-local addresses must use scope id,
+ * otherwise the session lookup will always fail
+ * and we'll have multiple sessions showing up.
+ *
+ * This problem only happens with single hop
+ * since it is not possible to have link-local
+ * address for multi hop sessions.
+ */
+ if (bpc->bpc_ipv4 == false
+ && IN6_IS_ADDR_LINKLOCAL(
+ &bpc->bpc_peer.sa_sin6.sin6_addr))
+ bpc->bpc_peer.sa_sin6.sin6_scope_id =
+ ptm_bfd_fetch_ifindex(bpc->bpc_localif);
}
}
void bfdd_zclient_init(struct zebra_privs_t *bfdd_priv)
{
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
assert(zclient != NULL);
zclient_init(zclient, ZEBRA_ROUTE_BFD, 0, bfdd_priv);
}
}
}
+
+void bgp_nht_register_enhe_capability_interfaces(struct peer *peer)
+{
+ struct bgp *bgp;
+ struct bgp_node *rn;
+ struct bgp_nexthop_cache *bnc;
+ struct nexthop *nhop;
+ struct interface *ifp;
+ struct prefix p;
+
+ if (peer->ifp)
+ return;
+
+ bgp = peer->bgp;
+
+ if (!bgp->nexthop_cache_table[AFI_IP6])
+ return;
+
+ if (!sockunion2hostprefix(&peer->su, &p)) {
+ if (BGP_DEBUG(nht, NHT))
+ zlog_debug("%s: Unable to convert prefix to sockunion",
+ __PRETTY_FUNCTION__);
+ return;
+ }
+
+ if (p.family != AF_INET6)
+ return;
+ rn = bgp_node_lookup(bgp->nexthop_cache_table[AFI_IP6], &p);
+
+ bnc = bgp_nexthop_get_node_info(rn);
+ if (!bnc)
+ return;
+
+ if (peer != bnc->nht_info)
+ return;
+
+ for (nhop = bnc->nexthop; nhop; nhop = nhop->next) {
+ ifp = if_lookup_by_index(nhop->ifindex,
+ nhop->vrf_id);
+ zclient_send_interface_radv_req(zclient,
+ nhop->vrf_id,
+ ifp, true,
+ BGP_UNNUM_DEFAULT_RA_INTERVAL);
+ }
+}
*/
extern void bgp_nht_register_nexthops(struct bgp *bgp);
+/*
+ * When we have the the PEER_FLAG_CAPABILITY_ENHE flag
+ * set on a peer *after* it has been brought up we need
+ * to notice and setup the interface based RA,
+ * this code can walk the registered nexthops and
+ * register the important ones with zebra for RA.
+ */
+extern void bgp_nht_register_enhe_capability_interfaces(struct peer *peer);
+
#endif /* _BGP_NHT_H */
zclient_num_connects = 0;
/* Set default values. */
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_BGP, 0, &bgpd_privs);
zclient->zebra_connected = bgp_zebra_connected;
zclient->router_id_update = bgp_router_id_update;
return 0;
}
+ if (set && flag == PEER_FLAG_CAPABILITY_ENHE)
+ bgp_nht_register_enhe_capability_interfaces(peer);
+
/*
* Update peer-group members, unless they are explicitely overriding
* peer-group configuration.
/* Update flag on peer-group member. */
COND_FLAG(member->flags, flag, set != member_invert);
+ if (set && flag == PEER_FLAG_CAPABILITY_ENHE)
+ bgp_nht_register_enhe_capability_interfaces(member);
+
/* Execute flag action on peer-group member. */
if (action.type == peer_change_reset)
peer_flag_modify_action(member, flag);
void vnc_zebra_init(struct thread_master *master)
{
/* Set default values. */
- zclient_vnc = zclient_new_notify(master, &zclient_options_default);
+ zclient_vnc = zclient_new(master, &zclient_options_default);
zclient_init(zclient_vnc, ZEBRA_ROUTE_VNC, 0, &bgpd_privs);
zclient_vnc->redistribute_route_add = vnc_zebra_read_route;
Add init.d startup files
^^^^^^^^^^^^^^^^^^^^^^^^
-.. code-block::
+.. code-block:: shell
sudo install -p -m 755 redhat/frr.init /etc/init.d/frr
sudo chkconfig --add frr
Enable FRR daemon at startup
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-.. code-block::
+.. code-block:: shell
sudo chkconfig frr on
Start FRR manually (or reboot)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-.. code-block::
+.. code-block:: shell
sudo /etc/init.d/frr start
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Although not strictly necessary, it's good practice to create empty
-configuration files _before_ starting FRR. This assures that the permissions
+configuration files _before_ starting FRR. This assures that the permissions
are correct. If the files are not already present, FRR will create them.
It's also important to consider _which_ files to create. FRR supports writing
Note: please check the `libyang build requirements
<https://github.com/CESNET/libyang/blob/master/README.md#build-requirements>`_
first.
-
-Libyang uses loadable libraries an YANG modules. It supports
-environment variables to allow overriding the load paths for each of
-these. With FRR, this override currently must be done at the time of
-running FRR's configure command using new options. The new options are:
-
-.. code-block:: shell
-
- --with-yangmodelsdir=DIR
- yang models directory (${datarootdir}/yang)
- --with-libyang-pluginsdir=DIR
- yangmodule plugins directory
- (${libdir}/frr/libyang_plugins)
-
-an example which uses the compile directory is:
-
-.. code-block:: shell
-
- ./configure --with-libyang-pluginsdir="`pwd`/yang/libyang_plugins/.libs" \
- --with-yangmodelsdir="`pwd`/yang"
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
-exclude_patterns = ['_build']
+exclude_patterns = ['_build', 'building-libyang.rst']
# The reST default role (used for this markup: `text`) to use for all
# documents.
-Release Build Procedure for FRR maintainers
-=========================================================
+Release Build Procedure for FRR Maintainers
+===========================================
1. Rename branch (if needed)
Command line parameters
-----------------------
-Command line parameters can be passed directly to a module by appending a
-colon to the module name when loading it, e.g. ``-M mymodule:myparameter``.
-The text after the colon will be accessible in the module's code through
+Command line parameters can be passed directly to a module by appending a
+colon to the module name when loading it, e.g. ``-M mymodule:myparameter``.
+The text after the colon will be accessible in the module's code through
``THIS_MODULE->load_args``. For example, see how the format parameter is
configured in the ``zfpm_init()`` function inside ``zebra_fpm.c``.
O O
/ \
O O
-
+
struct rnh
{
uint8_t flags;
-Debian
-======
+Packaging Debian
+================
(Tested on Ubuntu 12.04, 14.04, 16.04, 17.10, 18.04, Debian 8 and 9)
.. toctree::
:maxdepth: 2
+ maintainer-release-build
packaging-debian
.. todo: replace these with SVG
.. figure:: ../figures/threadmaster-single.png
:align: center
-
+
Lifecycle of a program using a single threadmaster.
The series of "task" boxes represents the current ready task queue. The various
.. todo: replace these with SVG
.. figure:: ../figures/threadmaster-multiple.png
:align: center
-
+
Lifecycle of a program using multiple pthreads, each running their own
``threadmaster``
Configure zebra to use `dir` for local state files, such as pid files and
unix sockets.
+.. option:: --with-yangmodelsdir <dir>
+
+ Look for YANG modules in `dir` [`prefix`/share/yang]. Note that the FRR
+ YANG modules will be installed here.
+
+.. option:: --with-libyang-pluginsdir <dir>
+
+ Look for libyang plugins in `dir` [`prefix`/lib/frr/libyang_plugins].
+ Note that the FRR libyang plugins will be installed here.
+
+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:
+.. code-block:: shell
+
+ ./configure --with-libyang-pluginsdir="`pwd`/yang/libyang_plugins/.libs" \
+ --with-yangmodelsdir="`pwd`/yang"
+
.. _least-privilege-support:
Least-Privilege Support
appropriate value.
:makevar:`VRF forwarding`
- General information on Linux VRF support can be found in
+ General information on Linux VRF support can be found in
https://www.kernel.org/doc/Documentation/networking/vrf.txt. Kernel
support for VRFs was introduced in 4.3 and improved upon through
4.13, which is the version most used in FRR testing (as of June
included in future kernel versions so upgrading your kernel may also
address this issue.
-
+
Building
^^^^^^^^
ISIS router
===========
-To start ISIS process you have to specify the ISIS router. As of this
+To start the ISIS process you have to specify the ISIS router. As of this
writing, *isisd* does not support multiple ISIS processes.
-.. index:: router isis WORD
-.. clicmd:: router isis WORD
-
-.. index:: no router isis WORD
-.. clicmd:: no router isis WORD
+.. index:: [no] router isis WORD
+.. clicmd:: [no] router isis WORD
Enable or disable the ISIS process by specifying the ISIS domain with
'WORD'. *isisd* does not yet support multiple ISIS processes but you must
ISIS interface
==============
-.. index:: ip router isis WORD
-.. clicmd:: ip router isis WORD
-
-.. index:: no ip router isis WORD
-.. clicmd:: no ip router isis WORD
-
.. _ip-router-isis-word:
- Activate ISIS adjacency on this interface. Note that the name
- of ISIS instance must be the same as the one used to configure the ISIS process
- (see command :clicmd:`router isis WORD`).
+.. index:: [no] <ip|ipv6> router isis WORD
+.. clicmd:: [no] <ip|ipv6> router isis WORD
+
+ Activate ISIS adjacency on this interface. Note that the name of ISIS
+ instance must be the same as the one used to configure the ISIS process (see
+ command :clicmd:`router isis WORD`). To enable IPv4, issue ``ip router isis
+ WORD``; to enable IPv6, issue ``ipv6 router isis WORD``.
.. index:: isis circuit-type [level-1 | level-1-2 | level-2]
.. clicmd:: isis circuit-type [level-1 | level-1-2 | level-2]
.. _starting-static:
-Starting STATIC
+Starting STATIC
===============
Default configuration file for *staticd* is :file:`staticd.conf`. The typical
initial form of the command. GATEWAY is gateway for the prefix it currently
must match the v4 or v6 route type specified at the start of the command.
GATEWAY can also be treated as an interface name. If the interface name
- is ``null0`` then zebra installs a blackhole route. TABLENO
+ is ``null0`` then zebra installs a blackhole route. TABLENO
is an optional parameter for namespaces that allows you to create the
route in a specified table associated with the vrf namespace. table will
be rejected if you are not using namespace based vrfs. ``nexthop-vrf``
- allows you to create a leaked route with a nexthop in the specified VRFNAME
+ allows you to create a leaked route with a nexthop in the specified VRFNAME
vrf VRFNAME allows you to create the route in a specified vrf.
``nexthop-vrf`` cannot be currently used with namespace based vrfs
currently as well.
Enable/disable link-detect on platforms which support this. Currently only
Linux and Solaris, and only where network interface drivers support
reporting link-state via the ``IFF_RUNNING`` flag.
-
+
In FRR, link-detect is on by default.
.. _link-parameters-commands:
{
struct zclient_options opt = {.receive_notify = false};
- zclient = zclient_new_notify(master, &opt);
+ zclient = zclient_new(master, &opt);
zclient_init(zclient, ZEBRA_ROUTE_EIGRP, 0, &eigrpd_privs);
zclient->zebra_connected = eigrp_zebra_connected;
for (ALL_LIST_ELEMENTS_RO(lsp0->lspu.frags, node, lsp)) {
if (lsp->tlvs)
lsp_inc_seqno(lsp, 0);
- else
+ else if (lsp->hdr.rem_lifetime) {
+ /* Purge should only be applied when the fragment has
+ * non-zero remaining lifetime.
+ */
lsp_purge(lsp, lsp0->level, NULL);
+ }
}
return;
void lsp_build_list_nonzero_ht(uint8_t *start_id, uint8_t *stop_id,
struct list *list, dict_t *lspdb)
{
- dnode_t *first, *last, *curr;
-
- first = dict_lower_bound(lspdb, start_id);
- if (!first)
- return;
-
- last = dict_upper_bound(lspdb, stop_id);
+ for (dnode_t *curr = dict_lower_bound(lspdb, start_id);
+ curr; curr = dict_next(lspdb, curr)) {
+ struct isis_lsp *lsp = curr->dict_data;
- curr = first;
-
- if (((struct isis_lsp *)(curr->dict_data))->hdr.rem_lifetime)
- listnode_add(list, first->dict_data);
-
- while (curr) {
- curr = dict_next(lspdb, curr);
- if (curr
- && ((struct isis_lsp *)(curr->dict_data))->hdr.rem_lifetime)
- listnode_add(list, curr->dict_data);
- if (curr == last)
+ if (memcmp(lsp->hdr.lsp_id, stop_id,
+ ISIS_SYS_ID_LEN + 2) > 0)
break;
- }
- return;
+ if (lsp->hdr.rem_lifetime)
+ listnode_add(list, lsp);
+ }
}
static void lsp_set_time(struct isis_lsp *lsp)
lsp->last_generated = time(NULL);
lsp_flood(lsp, NULL);
for (ALL_LIST_ELEMENTS_RO(lsp->lspu.frags, node, frag)) {
+ if (!frag->tlvs) {
+ /* Updating and flooding should only affect fragments
+ * carrying data
+ */
+ continue;
+ }
+
frag->hdr.lsp_bits = lsp_bits_generate(
level, area->overload_bit, area->attached_bit);
/* Set the lifetime values of all the fragments to the same
if ((area->is_type & level) == 0)
return ISIS_ERROR;
- if (monotime_since(&area->last_lsp_refresh_event[level - 1], NULL) < 50000L) {
+ if (monotime_since(&area->last_lsp_refresh_event[level - 1], NULL) < 100000L) {
sched_debug("ISIS (%s): Still unstable, postpone LSP L%d refresh",
area->area_tag, level);
_lsp_regenerate_schedule(area, level, 0, false,
void lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit)
{
- if (!fabricd) {
+ if (!fabricd)
lsp_set_all_srmflags(lsp, true);
- if (circuit)
- isis_tx_queue_del(circuit->tx_queue, lsp);
- } else {
+ else
fabricd_lsp_flood(lsp);
- }
+
+ if (circuit)
+ isis_tx_queue_del(circuit->tx_queue, lsp);
}
static int lsp_handle_adj_state_change(struct isis_adjacency *adj)
void isis_zebra_init(struct thread_master *master)
{
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
zclient_init(zclient, PROTO_TYPE, 0, &isisd_privs);
zclient->zebra_connected = isis_zebra_connected;
zclient->router_id_update = isis_router_id_update_zebra;
static void zclient_sync_init(unsigned short instance)
{
/* Initialize special zclient for synchronous message exchanges. */
- zclient_sync = zclient_new_notify(master, &zclient_options_default);
+ zclient_sync = zclient_new(master, &zclient_options_default);
zclient_sync->sock = -1;
zclient_sync->redist_default = ZEBRA_ROUTE_LDP;
zclient_sync->instance = instance;
ldp_zebra_init(struct thread_master *master)
{
/* Set default values. */
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_LDP, 0, &ldpd_privs);
/* set callbacks */
events = list_new();
agentx_events_update();
agentx_enabled = 1;
- return CMD_SUCCESS;
}
- vty_out(vty, "SNMP AgentX already enabled\n");
+
return CMD_SUCCESS;
}
struct zclient_options zclient_options_default = {.receive_notify = false};
/* Allocate zclient structure. */
-struct zclient *zclient_new_notify(struct thread_master *master,
- struct zclient_options *opt)
+struct zclient *zclient_new(struct thread_master *master,
+ struct zclient_options *opt)
{
struct zclient *zclient;
zclient = XCALLOC(MTYPE_ZCLIENT, sizeof(struct zclient));
* @param zclient a pointer to zclient structure
* @return socket fd just to make sure that connection established
* @see zclient_init
- * @see zclient_new_notify
+ * @see zclient_new
*/
int zclient_socket_connect(struct zclient *zclient)
{
bool receive_notify;
};
-/* Prototypes of zebra client service functions. */
-extern struct zclient *zclient_new(struct thread_master *);
-
-/* clang-format off */
-#if CONFDATE > 20181101
-CPP_NOTICE("zclient_new_notify can take over or zclient_new now");
-#endif
-/* clang-format on */
-
extern struct zclient_options zclient_options_default;
-extern struct zclient *zclient_new_notify(struct thread_master *m,
- struct zclient_options *opt);
-
-#define zclient_new(A) \
- zclient_new_notify((A), &zclient_options_default); \
- CPP_WARN("Please transition to using zclient_new_notify");
+extern struct zclient *zclient_new(struct thread_master *m,
+ struct zclient_options *opt);
extern void zclient_init(struct zclient *, int, unsigned short,
struct zebra_privs_t *privs);
zebra_rib[AFI_IP] = route_table_init();
zebra_rib[AFI_IP6] = route_table_init();
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
zclient->zebra_connected = nhrp_zebra_connected;
zclient->interface_add = nhrp_interface_add;
zclient->interface_delete = nhrp_interface_delete;
DEFUN (area_filter_list,
area_filter_list_cmd,
- "area A.B.C.D filter-list prefix WORD <in|out>",
+ "area <A.B.C.D|(0-4294967295)> filter-list prefix WORD <in|out>",
"OSPF6 area parameters\n"
"OSPF6 area ID in IP address format\n"
+ "OSPF6 area ID as a decimal value\n"
"Filter networks between OSPF6 areas\n"
"Filter prefixes between OSPF6 areas\n"
"Name of an IPv6 prefix-list\n"
DEFUN (no_area_filter_list,
no_area_filter_list_cmd,
- "no area A.B.C.D filter-list prefix WORD <in|out>",
+ "no area <A.B.C.D|(0-4294967295)> filter-list prefix WORD <in|out>",
NO_STR
"OSPF6 area parameters\n"
"OSPF6 area ID in IP address format\n"
+ "OSPF6 area ID as a decimal value\n"
"Filter networks between OSPF6 areas\n"
"Filter prefixes between OSPF6 areas\n"
"Name of an IPv6 prefix-list\n"
DEFUN (area_import_list,
area_import_list_cmd,
- "area A.B.C.D import-list NAME",
+ "area <A.B.C.D|(0-4294967295)> import-list NAME",
"OSPF6 area parameters\n"
"OSPF6 area ID in IP address format\n"
+ "OSPF6 area ID as a decimal value\n"
"Set the filter for networks from other areas announced to the specified one\n"
"Name of the acess-list\n")
{
DEFUN (no_area_import_list,
no_area_import_list_cmd,
- "no area A.B.C.D import-list NAME",
+ "no area <A.B.C.D|(0-4294967295)> import-list NAME",
NO_STR
"OSPF6 area parameters\n"
"OSPF6 area ID in IP address format\n"
+ "OSPF6 area ID as a decimal value\n"
"Unset the filter for networks announced to other areas\n"
"Name of the access-list\n")
{
DEFUN (area_export_list,
area_export_list_cmd,
- "area A.B.C.D export-list NAME",
+ "area <A.B.C.D|(0-4294967295)> export-list NAME",
"OSPF6 area parameters\n"
"OSPF6 area ID in IP address format\n"
+ "OSPF6 area ID as a decimal value\n"
"Set the filter for networks announced to other areas\n"
"Name of the acess-list\n")
{
DEFUN (no_area_export_list,
no_area_export_list_cmd,
- "no area A.B.C.D export-list NAME",
+ "no area <A.B.C.D|(0-4294967295)> export-list NAME",
NO_STR
"OSPF6 area parameters\n"
"OSPF6 area ID in IP address format\n"
+ "OSPF6 area ID as a decimal value\n"
"Unset the filter for networks announced to other areas\n"
"Name of the access-list\n")
{
void ospf6_zebra_init(struct thread_master *master)
{
/* Allocate zebra structure. */
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_OSPF6, 0, &ospf6d_privs);
zclient->zebra_connected = ospf6_zebra_connected;
zclient->router_id_update = ospf6_router_id_update_zebra;
void ospf_zebra_init(struct thread_master *master, unsigned short instance)
{
/* Allocate zebra structure. */
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_OSPF, instance, &ospfd_privs);
zclient->zebra_connected = ospf_zebra_connected;
zclient->router_id_update = ospf_router_id_update_zebra;
{
struct zclient_options opt = { .receive_notify = true };
- zclient = zclient_new_notify(master, &opt);
+ zclient = zclient_new(master, &opt);
zclient_init(zclient, ZEBRA_ROUTE_PBR, 0, &pbr_privs);
zclient->zebra_connected = zebra_connected;
void pim_zebra_init(void)
{
/* Socket for receiving updates from Zebra daemon */
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
zclient->zebra_connected = pim_zebra_connected;
zclient->router_id_update = pim_router_id_update_zebra;
void zclient_lookup_new(void)
{
- zlookup = zclient_new_notify(master, &zclient_options_default);
+ zlookup = zclient_new(master, &zclient_options_default);
if (!zlookup) {
flog_err(EC_LIB_ZAPI_SOCKET, "%s: zclient_new() failure",
__PRETTY_FUNCTION__);
void rip_zclient_init(struct thread_master *master)
{
/* Set default value to the zebra client structure. */
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_RIP, 0, &ripd_privs);
zclient->zebra_connected = rip_zebra_connected;
zclient->interface_add = rip_interface_add;
void zebra_init(struct thread_master *master)
{
/* Allocate zebra structure. */
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
zclient_init(zclient, ZEBRA_ROUTE_RIPNG, 0, &ripngd_privs);
zclient->zebra_connected = ripng_zebra_connected;
{
struct zclient_options opt = {.receive_notify = true};
- zclient = zclient_new_notify(master, &opt);
+ zclient = zclient_new(master, &opt);
zclient_init(zclient, ZEBRA_ROUTE_SHARP, 0, &sharp_privs);
zclient->zebra_connected = zebra_connected;
{
struct zclient_options opt = { .receive_notify = true };
- zclient = zclient_new_notify(master, &opt);
+ zclient = zclient_new(master, &opt);
zclient_init(zclient, ZEBRA_ROUTE_STATIC, 0, &static_privs);
zclient->zebra_capabilities = static_zebra_capabilities;
/bgpd/test_peer_attr
/isisd/test_fuzz_isis_tlv
/isisd/test_fuzz_isis_tlv_tests.h
+/isisd/test_isis_lspdb
/isisd/test_isis_vertex_queue
/lib/cli/test_cli
/lib/cli/test_cli_clippy.c
{
qobj_init();
master = thread_master_create(NULL);
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
bgp_master_init(master);
vrf_init(NULL, NULL, NULL, NULL, NULL);
bgp_option_set(BGP_OPT_NO_LISTEN);
--- /dev/null
+#include <zebra.h>
+
+#include "isisd/isis_lsp.c"
+
+struct thread_master *master;
+
+int isis_sock_init(struct isis_circuit *circuit);
+int isis_sock_init(struct isis_circuit *circuit)
+{
+ return 0;
+}
+
+struct zebra_privs_t isisd_privs;
+
+static void test_lsp_build_list_nonzero_ht(void)
+{
+ uint8_t lsp_id1[8] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00
+ };
+ uint8_t lsp_id_end[8] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x5f, 0x00
+ };
+ uint8_t lsp_id2[8] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00
+ };
+
+ struct isis_area *area = calloc(sizeof(*area), 1);
+
+ area->lsp_mtu = 1500;
+
+ dict_t *lspdb = lsp_db_init();
+
+ struct isis_lsp *lsp1 = lsp_new(area, lsp_id1, 6000, 0, 0, 0, NULL,
+ ISIS_LEVEL2);
+
+ lsp_insert(lsp1, lspdb);
+
+ struct isis_lsp *lsp2 = lsp_new(area, lsp_id2, 6000, 0, 0, 0, NULL,
+ ISIS_LEVEL2);
+
+ lsp_insert(lsp2, lspdb);
+
+ struct list *list = list_new();
+
+ lsp_build_list_nonzero_ht(lsp_id1, lsp_id_end, list, lspdb);
+ assert(list->count == 1);
+ assert(listgetdata(listhead(list)) == lsp1);
+ list_delete_all_node(list);
+
+ lsp_id_end[5] = 0x03;
+ lsp_id_end[6] = 0x00;
+
+ lsp_build_list_nonzero_ht(lsp_id1, lsp_id_end, list, lspdb);
+ assert(list->count == 2);
+ assert(listgetdata(listhead(list)) == lsp1);
+ assert(listgetdata(listtail(list)) == lsp2);
+ list_delete_all_node(list);
+
+ memcpy(lsp_id1, lsp_id2, sizeof(lsp_id1));
+
+ lsp_build_list_nonzero_ht(lsp_id1, lsp_id_end, list, lspdb);
+ assert(list->count == 1);
+ assert(listgetdata(listhead(list)) == lsp2);
+ list_delete_all_node(list);
+
+ lsp_id1[5] = 0x03;
+ lsp_id_end[5] = 0x04;
+
+ lsp_build_list_nonzero_ht(lsp_id1, lsp_id_end, list, lspdb);
+ assert(list->count == 0);
+ list_delete_all_node(list);
+
+ lsp_id1[5] = 0x00;
+
+ lsp_build_list_nonzero_ht(lsp_id1, lsp_id_end, list, lspdb);
+ assert(list->count == 2);
+ assert(listgetdata(listhead(list)) == lsp1);
+ assert(listgetdata(listtail(list)) == lsp2);
+ list_delete_all_node(list);
+}
+
+int main(int argc, char **argv)
+{
+ isis = calloc(sizeof(*isis), 1);
+ test_lsp_build_list_nonzero_ht();
+ return 0;
+}
--- /dev/null
+import frrtest
+
+class TestIsisLSPDB(frrtest.TestMultiOut):
+ program = './test_isis_lspdb'
+
+TestIsisLSPDB.exit_cleanly()
else
TESTS_ISISD = \
tests/isisd/test_fuzz_isis_tlv \
+ tests/isisd/test_isis_lspdb \
tests/isisd/test_isis_vertex_queue \
# end
endif
tests_isisd_test_fuzz_isis_tlv_LDADD = $(ISISD_TEST_LDADD)
tests_isisd_test_fuzz_isis_tlv_SOURCES = tests/isisd/test_fuzz_isis_tlv.c
nodist_tests_isisd_test_fuzz_isis_tlv_SOURCES = tests/isisd/test_fuzz_isis_tlv_tests.h
+tests_isisd_test_isis_lspdb_CFLAGS = $(TESTS_CFLAGS)
+tests_isisd_test_isis_lspdb_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_isisd_test_isis_lspdb_LDADD = $(ISISD_TEST_LDADD)
+tests_isisd_test_isis_lspdb_SOURCES = tests/isisd/test_isis_lspdb.c
tests_isisd_test_isis_vertex_queue_CFLAGS = $(TESTS_CFLAGS)
tests_isisd_test_isis_vertex_queue_CPPFLAGS = $(TESTS_CPPFLAGS)
tests_isisd_test_isis_vertex_queue_LDADD = $(ISISD_TEST_LDADD)
tests/helpers/python/frrtest.py \
tests/isisd/test_fuzz_isis_tlv.py \
tests/isisd/test_fuzz_isis_tlv_tests.h.gz \
+ tests/isisd/test_isis_lspdb.py \
tests/isisd/test_isis_vertex_queue.py \
tests/lib/cli/test_commands.in \
tests/lib/cli/test_commands.py \
{
frr_zclient_addr(&zclient_addr, &zclient_addr_len, lm_zserv_path);
- zclient = zclient_new_notify(master, &zclient_options_default);
+ zclient = zclient_new(master, &zclient_options_default);
/* zclient_init(zclient, ZEBRA_LABEL_MANAGER, 0); */
zclient->sock = -1;
zclient->redist_default = ZEBRA_ROUTE_LDP;
# The list of daemons to watch is automatically generated by the init script.
watchfrr_enable=yes
-watchfrr_options=(-d -r /usr/sbin/servicebBfrrbBrestartbB%s -s /usr/sbin/servicebBfrrbBstartbB%s -k /usr/sbin/servicebBfrrbBstopbB%s -b bB)
+
+watchfrr_options=(-d -r /usr/lib/frr/frrbBrestartbB%s -s /usr/lib/frr/frrbBstartbB%s -k /usr/lib/frr/frrbBstopbB%s -b bB)
# If valgrind_enable is 'yes' the frr daemons will be started via valgrind.
# The use case for doing so is tracking down memory leaks, etc in frr.
echo -n " $1"
fi
+
${SSD} \
--start \
--pidfile=`pidfile $1` \
-- \
`eval echo "$""$1""_options"` -n "$2"
else
- echo -n " $1"
if ! check_daemon $1; then
echo -n " (binary does not exist)"
return;
# Now we have to wait until $DAEMON has _really_ stopped.
#
if test -n "$PID" && kill -0 $PID 2>/dev/null; then
- echo -n " (waiting) ."
cnt=0
while kill -0 $PID 2>/dev/null; do
cnt=`expr $cnt + 1`
break
fi
sleep 2
- echo -n "."
done
fi
- echo -n " $inst"
rm -f `pidfile $inst`
rm -f `vtyfile $inst`
# Start if at least one daemon is activated.
if [ $found_one -eq 1 ]; then
- echo -n "Starting Frr monitor daemon:"
start watchfrr
echo "."
fi
wanted_prio=$1
daemon_list=${daemon:-$DAEMONS}
- echo -n "Starting Frr daemons (prio:$wanted_prio):"
-
for prio_i in `seq 1 $wanted_prio`; do
for daemon_name in $daemon_list; do
eval daemon_prio=\$${daemon_name}
eval "file_list_suffix="$V_PATH"/"$daemon_name-*""
for pidfile in $file_list_suffix.pid; do
${SSD} --stop --quiet --oknodo --pidfile "$pidfile"
- echo -n "."
rm -rf "$pidfile"
done
for vtyfile in $file_list_suffix.vty; do
fi
done
done
- echo "."
}
check_status()
}
}
-static void netlink_determine_zebra_iftype(char *kind, zebra_iftype_t *zif_type)
+static void netlink_determine_zebra_iftype(const char *kind,
+ zebra_iftype_t *zif_type)
{
*zif_type = ZEBRA_IF_OTHER;
*zif_type = ZEBRA_IF_MACVLAN;
else if (strcmp(kind, "veth") == 0)
*zif_type = ZEBRA_IF_VETH;
+ else if (strcmp(kind, "bond") == 0)
+ *zif_type = ZEBRA_IF_BOND;
+ else if (strcmp(kind, "bond_slave") == 0)
+ *zif_type = ZEBRA_IF_BOND_SLAVE;
}
#define parse_rtattr_nested(tb, max, rta) \
zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE;
ifindex_t bridge_ifindex = IFINDEX_INTERNAL;
ifindex_t link_ifindex = IFINDEX_INTERNAL;
+ ifindex_t bond_ifindex = IFINDEX_INTERNAL;
struct zebra_if *zif;
zns = zebra_ns_lookup(ns_id);
if (linkinfo[IFLA_INFO_SLAVE_KIND])
slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]);
- netlink_determine_zebra_iftype(kind, &zif_type);
+ if ((slave_kind != NULL) && strcmp(slave_kind, "bond") == 0)
+ netlink_determine_zebra_iftype("bond_slave", &zif_type);
+ else
+ netlink_determine_zebra_iftype(kind, &zif_type);
}
/* If VRF, create the VRF structure itself. */
zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE;
bridge_ifindex =
*(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
+ } else if (slave_kind && (strcmp(slave_kind, "bond") == 0)) {
+ zif_slave_type = ZEBRA_IF_SLAVE_BOND;
+ bond_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
} else
zif_slave_type = ZEBRA_IF_SLAVE_OTHER;
}
netlink_interface_update_l2info(ifp, linkinfo[IFLA_INFO_DATA], 1);
if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
zebra_l2if_update_bridge_slave(ifp, bridge_ifindex);
+ else if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
+ zebra_l2if_update_bond_slave(ifp, bond_ifindex);
return 0;
}
zebra_iftype_t zif_type = ZEBRA_IF_OTHER;
zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE;
ifindex_t bridge_ifindex = IFINDEX_INTERNAL;
+ ifindex_t bond_ifindex = IFINDEX_INTERNAL;
ifindex_t link_ifindex = IFINDEX_INTERNAL;
zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE;
bridge_ifindex =
*(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
+ } else if (slave_kind
+ && (strcmp(slave_kind, "bond") == 0)) {
+ zif_slave_type = ZEBRA_IF_SLAVE_BOND;
+ bond_ifindex =
+ *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
} else
zif_slave_type = ZEBRA_IF_SLAVE_OTHER;
}
if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
zebra_l2if_update_bridge_slave(ifp,
bridge_ifindex);
+ else if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
+ zebra_l2if_update_bond_slave(ifp, bond_ifindex);
} else if (ifp->vrf_id != vrf_id) {
/* VRF change for an interface. */
if (IS_ZEBRA_DEBUG_KERNEL)
if_handle_vrf_change(ifp, vrf_id);
} else {
- int was_bridge_slave;
+ bool was_bridge_slave, was_bond_slave;
/* Interface update. */
if (IS_ZEBRA_DEBUG_KERNEL)
/* Update interface type - NOTE: Only slave_type can
* change. */
was_bridge_slave = IS_ZEBRA_IF_BRIDGE_SLAVE(ifp);
+ was_bond_slave = IS_ZEBRA_IF_BOND_SLAVE(ifp);
zebra_if_set_ziftype(ifp, zif_type, zif_slave_type);
netlink_interface_update_hw_addr(tb, ifp);
if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) || was_bridge_slave)
zebra_l2if_update_bridge_slave(ifp,
bridge_ifindex);
+ else if (IS_ZEBRA_IF_BOND_SLAVE(ifp) || was_bond_slave)
+ zebra_l2if_update_bond_slave(ifp, bond_ifindex);
}
} else {
/* Delete interface notification from kernel */
return "VETH";
break;
+ case ZEBRA_IF_BOND:
+ return "bond";
+
+ case ZEBRA_IF_BOND_SLAVE:
+ return "bond_slave";
+
+ case ZEBRA_IF_MACVLAN:
+ return "macvlan";
+
default:
return "Unknown";
break;
br_slave->bridge_ifindex);
}
+ if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) {
+ struct zebra_l2info_bondslave *bond_slave;
+
+ bond_slave = &zebra_if->bondslave_info;
+ if (bond_slave->bond_ifindex != IFINDEX_INTERNAL)
+ vty_out(vty, " Master (bond) ifindex %u\n",
+ bond_slave->bond_ifindex);
+ }
+
if (zebra_if->link_ifindex != IFINDEX_INTERNAL) {
vty_out(vty, " Link ifindex %u", zebra_if->link_ifindex);
if (zebra_if->link)
+
/* Interface function header.
* Copyright (C) 1999 Kunihiro Ishiguro
*
ZEBRA_IF_VLAN, /* VLAN sub-interface */
ZEBRA_IF_MACVLAN, /* MAC VLAN interface*/
ZEBRA_IF_VETH, /* VETH interface*/
+ ZEBRA_IF_BOND, /* Bond */
+ ZEBRA_IF_BOND_SLAVE, /* Bond */
} zebra_iftype_t;
/* Zebra "slave" interface type */
ZEBRA_IF_SLAVE_NONE, /* Not a slave */
ZEBRA_IF_SLAVE_VRF, /* Member of a VRF */
ZEBRA_IF_SLAVE_BRIDGE, /* Member of a bridge */
+ ZEBRA_IF_SLAVE_BOND, /* Bond member */
ZEBRA_IF_SLAVE_OTHER, /* Something else - e.g., bond slave */
} zebra_slave_iftype_t;
*/
struct zebra_l2info_brslave brslave_info;
+ struct zebra_l2info_bondslave bondslave_info;
+
/* Link fields - for sub-interfaces. */
ifindex_t link_ifindex;
struct interface *link;
#define IS_ZEBRA_IF_VRF_SLAVE(ifp) \
(((struct zebra_if *)(ifp->info))->zif_slave_type == ZEBRA_IF_SLAVE_VRF)
+#define IS_ZEBRA_IF_BOND_SLAVE(ifp) \
+ (((struct zebra_if *)(ifp->info))->zif_slave_type \
+ == ZEBRA_IF_SLAVE_BOND)
+
extern void zebra_if_init(void);
extern struct interface *if_lookup_by_index_per_ns(struct zebra_ns *, uint32_t);
lm_zserv_path);
/* Set default values. */
- zclient = zclient_new_notify(zebrad.master, &zclient_options_default);
+ zclient = zclient_new(zebrad.master, &zclient_options_default);
zclient->privs = &zserv_privs;
zclient->sock = -1;
zclient->t_connect = NULL;
br_slave->br_if = NULL;
}
+void zebra_l2_map_slave_to_bond(struct zebra_l2info_bondslave *bond_slave)
+{
+ struct interface *bond_if;
+
+ /* TODO: Handle change of master */
+ bond_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
+ bond_slave->bond_ifindex);
+ if (bond_if)
+ bond_slave->bond_if = bond_if;
+}
+
+void zebra_l2_unmap_slave_from_bond(struct zebra_l2info_bondslave *bond_slave)
+{
+ if (bond_slave != NULL)
+ bond_slave->bond_if = NULL;
+}
+
/*
* Handle Bridge interface add or update. Update relevant info,
* map slaves (if any) to the bridge.
zebra_l2_unmap_slave_from_bridge(&zif->brslave_info);
}
}
+
+void zebra_l2if_update_bond_slave(struct interface *ifp, ifindex_t bond_ifindex)
+{
+ struct zebra_if *zif;
+ ifindex_t old_bond_ifindex;
+
+ zif = ifp->info;
+ assert(zif);
+
+ old_bond_ifindex = zif->bondslave_info.bond_ifindex;
+ if (old_bond_ifindex == bond_ifindex)
+ return;
+
+ zif->bondslave_info.bond_ifindex = bond_ifindex;
+
+ /* Set up or remove link with master */
+ if (bond_ifindex != IFINDEX_INTERNAL)
+ zebra_l2_map_slave_to_bond(&zif->bondslave_info);
+ else if (old_bond_ifindex != IFINDEX_INTERNAL)
+ zebra_l2_unmap_slave_from_bond(&zif->bondslave_info);
+}
vlanid_t access_vlan; /* Access VLAN - for VLAN-aware bridge. */
};
+struct zebra_l2info_bondslave {
+ ifindex_t bond_ifindex; /* Bridge Master */
+ struct interface *bond_if; /* Pointer to master */
+};
+
union zebra_l2if_info {
struct zebra_l2info_bridge br;
struct zebra_l2info_vlan vl;
extern void zebra_l2_map_slave_to_bridge(struct zebra_l2info_brslave *br_slave);
extern void
zebra_l2_unmap_slave_from_bridge(struct zebra_l2info_brslave *br_slave);
+extern void
+zebra_l2_map_slave_to_bond(struct zebra_l2info_bondslave *bond_slave);
+extern void
+zebra_l2_unmap_slave_from_bond(struct zebra_l2info_bondslave *bond_slave);
extern void zebra_l2_bridge_add_update(struct interface *ifp,
struct zebra_l2info_bridge *bridge_info,
int add);
extern void zebra_l2if_update_bridge_slave(struct interface *ifp,
ifindex_t bridge_ifindex);
+extern void zebra_l2if_update_bond_slave(struct interface *ifp,
+ ifindex_t bond_ifindex);
#endif /* _ZEBRA_L2_H */
if (newhop->ifindex) {
resolved_hop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
resolved_hop->ifindex = newhop->ifindex;
- if (newhop->flags & NEXTHOP_FLAG_ONLINK)
- resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
}
break;
case NEXTHOP_TYPE_IPV6:
break;
}
+ if (newhop->flags & NEXTHOP_FLAG_ONLINK)
+ resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
+
/* Copy labels of the resolved route */
if (newhop->nh_label)
nexthop_add_labels(resolved_hop, newhop->nh_label_type,
/* Match function should return 1 if match is success else return
zero. */
-static route_map_result_t route_match_ip_address(void *rule,
- const struct prefix *prefix,
- route_map_object_t type,
- void *object)
+static route_map_result_t route_match_address(afi_t afi, void *rule,
+ const struct prefix *prefix,
+ route_map_object_t type,
+ void *object)
{
struct access_list *alist;
if (type == RMAP_ZEBRA) {
- alist = access_list_lookup(AFI_IP, (char *)rule);
+ alist = access_list_lookup(afi, (char *)rule);
if (alist == NULL)
return RMAP_NOMATCH;
return RMAP_NOMATCH;
}
+static route_map_result_t route_match_ip_address(void *rule,
+ const struct prefix *prefix,
+ route_map_object_t type,
+ void *object)
+{
+ return route_match_address(AFI_IP, rule, prefix, type, object);
+}
+
+static route_map_result_t route_match_ipv6_address(void *rule,
+ const struct prefix *prefix,
+ route_map_object_t type,
+ void *object)
+
+{
+ return route_match_address(AFI_IP6, rule, prefix, type, object);
+}
+
/* Route map `ip address' match statement. `arg' should be
access-list name. */
-static void *route_match_ip_address_compile(const char *arg)
+static void *route_match_address_compile(const char *arg)
{
return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
}
/* Free route map's compiled `ip address' value. */
-static void route_match_ip_address_free(void *rule)
+static void route_match_address_free(void *rule)
{
XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
}
/* Route map commands for ip address matching. */
static struct route_map_rule_cmd route_match_ip_address_cmd = {
- "ip address", route_match_ip_address, route_match_ip_address_compile,
- route_match_ip_address_free};
+ "ip address", route_match_ip_address, route_match_address_compile,
+ route_match_address_free};
+
+/* Route map commands for ipv6 address matching. */
+static struct route_map_rule_cmd route_match_ipv6_address_cmd = {
+ "ipv6 address", route_match_ipv6_address, route_match_address_compile,
+ route_match_address_free};
/* `match ip address prefix-list PREFIX_LIST' */
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_ipv6_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);