summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am8
-rw-r--r--lib/agentx.c24
-rw-r--r--lib/bfd.c7
-rw-r--r--lib/bfd.h7
-rw-r--r--lib/bitfield.h7
-rw-r--r--lib/buffer.c9
-rw-r--r--lib/buffer.h7
-rw-r--r--lib/command.c476
-rw-r--r--lib/command.h94
-rw-r--r--lib/command_graph.c478
-rw-r--r--lib/command_graph.h119
-rw-r--r--lib/command_lex.l3
-rw-r--r--lib/command_match.c52
-rw-r--r--lib/command_match.h7
-rw-r--r--lib/command_parse.y58
-rw-r--r--lib/csv.c7
-rw-r--r--lib/csv.h7
-rw-r--r--lib/distribute.c7
-rw-r--r--lib/distribute.h7
-rw-r--r--lib/event_counter.c7
-rw-r--r--lib/event_counter.h7
-rw-r--r--lib/fifo.h36
-rw-r--r--lib/filter.c7
-rw-r--r--lib/filter.h7
-rw-r--r--lib/frr_pthread.c183
-rw-r--r--lib/frr_pthread.h144
-rw-r--r--lib/frratomic.h118
-rw-r--r--lib/getopt.c48
-rw-r--r--lib/getopt.h38
-rw-r--r--lib/getopt1.c40
-rw-r--r--lib/grammar_sandbox.c25
-rw-r--r--lib/grammar_sandbox_main.c4
-rw-r--r--lib/graph.c7
-rw-r--r--lib/graph.h7
-rw-r--r--lib/hash.c7
-rw-r--r--lib/hash.h36
-rw-r--r--lib/if.c42
-rw-r--r--lib/if.h36
-rw-r--r--lib/if_rmap.c7
-rw-r--r--lib/if_rmap.h7
-rw-r--r--lib/json.c7
-rw-r--r--lib/json.h7
-rw-r--r--lib/keychain.c36
-rw-r--r--lib/keychain.h7
-rw-r--r--lib/libfrr.c6
-rw-r--r--lib/libfrr.h6
-rw-r--r--lib/libospf.h7
-rw-r--r--lib/linklist.c7
-rw-r--r--lib/linklist.h7
-rw-r--r--lib/log.c20
-rw-r--r--lib/log.h10
-rw-r--r--lib/log_int.h7
-rw-r--r--lib/memory.c150
-rw-r--r--lib/memory.h43
-rw-r--r--lib/memory_vty.c6
-rw-r--r--lib/memory_vty.h36
-rw-r--r--lib/mpls.h15
-rw-r--r--lib/network.c7
-rw-r--r--lib/network.h7
-rw-r--r--lib/nexthop.c29
-rw-r--r--lib/nexthop.h8
-rw-r--r--lib/ns.c7
-rw-r--r--lib/ns.h7
-rw-r--r--lib/pid_output.c7
-rw-r--r--lib/plist.c43
-rw-r--r--lib/plist.h7
-rw-r--r--lib/plist_int.h7
-rw-r--r--lib/pqueue.c44
-rw-r--r--lib/pqueue.h37
-rw-r--r--lib/prefix.c13
-rw-r--r--lib/prefix.h9
-rw-r--r--lib/privs.c8
-rw-r--r--lib/privs.h7
-rw-r--r--lib/ptm_lib.c7
-rw-r--r--lib/ptm_lib.h7
-rw-r--r--lib/qobj.c7
-rw-r--r--lib/route_types.txt2
-rw-r--r--lib/routemap.c64
-rw-r--r--lib/routemap.h7
-rw-r--r--lib/sha256.c433
-rw-r--r--lib/sha256.h58
-rw-r--r--lib/sigevent.c35
-rw-r--r--lib/sigevent.h7
-rw-r--r--lib/smux.c18
-rw-r--r--lib/smux.h7
-rw-r--r--lib/snmp.c7
-rw-r--r--lib/sockopt.c7
-rw-r--r--lib/sockopt.h7
-rw-r--r--lib/sockunion.c7
-rw-r--r--lib/sockunion.h7
-rw-r--r--lib/spf_backoff.c23
-rw-r--r--lib/spf_backoff.h7
-rw-r--r--lib/srcdest_table.c7
-rw-r--r--lib/srcdest_table.h7
-rw-r--r--lib/stream.c34
-rw-r--r--lib/stream.h10
-rw-r--r--lib/strlcat.c33
-rw-r--r--lib/strlcpy.c33
-rw-r--r--lib/systemd.c42
-rw-r--r--lib/systemd.h38
-rw-r--r--lib/table.c7
-rw-r--r--lib/table.h7
-rw-r--r--lib/thread.c494
-rw-r--r--lib/thread.h128
-rw-r--r--lib/vector.c7
-rw-r--r--lib/vector.h7
-rw-r--r--lib/vrf.c63
-rw-r--r--lib/vrf.h58
-rw-r--r--lib/vrf_int.h56
-rw-r--r--lib/vty.c65
-rw-r--r--lib/vty.h36
-rw-r--r--lib/wheel.c22
-rw-r--r--lib/wheel.h7
-rw-r--r--lib/workqueue.c12
-rw-r--r--lib/workqueue.h7
-rw-r--r--lib/zassert.h7
-rw-r--r--lib/zclient.c87
-rw-r--r--lib/zclient.h22
-rw-r--r--lib/zebra.h51
119 files changed, 3283 insertions, 1602 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 14b7130c8a..a1b78d3c4d 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -17,6 +17,7 @@ libfrr_la_SOURCES = \
network.c pid_output.c getopt.c getopt1.c \
checksum.c vector.c linklist.c vty.c \
graph.c command_parse.y command_lex.l command_match.c \
+ command_graph.c \
command.c \
sockunion.c prefix.c thread.c if.c buffer.c table.c hash.c \
filter.c routemap.c distribute.c stream.c log.c plist.c \
@@ -32,8 +33,10 @@ libfrr_la_SOURCES = \
libfrr.c \
strlcpy.c \
strlcat.c \
+ sha256.c \
module.c \
hook.c \
+ frr_pthread.c \
# end
BUILT_SOURCES = route_types.h gitversion.h command_parse.h command_lex.h
@@ -54,9 +57,11 @@ libfrrsnmp_la_SOURCES = \
#end
pkginclude_HEADERS = \
+ frratomic.h \
buffer.h checksum.h filter.h getopt.h hash.h \
if.h linklist.h log.h \
graph.h command_match.h \
+ command_graph.h \
command.h \
memory.h network.h prefix.h routemap.h distribute.h sockunion.h \
stream.h table.h thread.h vector.h version.h vty.h zebra.h \
@@ -73,6 +78,9 @@ pkginclude_HEADERS = \
module.h \
hook.h \
libfrr.h \
+ sha256.h \
+ frr_pthread.h \
+ vrf_int.h \
# end
noinst_HEADERS = \
diff --git a/lib/agentx.c b/lib/agentx.c
index 11d5c9385d..fda634bb86 100644
--- a/lib/agentx.c
+++ b/lib/agentx.c
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
@@ -85,8 +84,11 @@ agentx_events_update(void)
FD_ZERO (&fds);
snmp_select_info (&maxfd, &fds, &timeout, &block);
- if (!block)
- timeout_thr = thread_add_timer_tv (agentx_tm, agentx_timeout, NULL, &timeout);
+ if (!block) {
+ timeout_thr = NULL;
+ thread_add_timer_tv(agentx_tm, agentx_timeout, NULL, &timeout,
+ &timeout_thr);
+ }
ln = listhead (events);
thr = ln ? listgetdata (ln) : NULL;
@@ -114,7 +116,8 @@ agentx_events_update(void)
else if (FD_ISSET (fd, &fds))
{
struct listnode *newln;
- thr = thread_add_read (agentx_tm, agentx_read, NULL, fd);
+ thr = NULL;
+ thread_add_read(agentx_tm, agentx_read, NULL, fd, &thr);
newln = listnode_add_before (events, ln, thr);
thr->arg = newln;
}
@@ -134,7 +137,8 @@ agentx_events_update(void)
static struct cmd_node agentx_node =
{
SMUX_NODE,
- "" /* AgentX has no interface. */
+ "", /* AgentX has no interface. */
+ 1
};
/* Logging NetSNMP messages */
@@ -165,7 +169,7 @@ config_write_agentx (struct vty *vty)
{
if (agentx_enabled)
vty_out (vty, "agentx%s", VTY_NEWLINE);
- return 0;
+ return 1;
}
DEFUN (agentx_enable,
@@ -183,7 +187,7 @@ DEFUN (agentx_enable,
return CMD_SUCCESS;
}
vty_out (vty, "SNMP AgentX already enabled%s", VTY_NEWLINE);
- return CMD_WARNING;
+ return CMD_SUCCESS;
}
DEFUN (no_agentx,
diff --git a/lib/bfd.c b/lib/bfd.c
index b651a05a09..217fc09722 100644
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -15,10 +15,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
diff --git a/lib/bfd.h b/lib/bfd.h
index e636e4426f..f23ff3bd8e 100644
--- a/lib/bfd.h
+++ b/lib/bfd.h
@@ -15,10 +15,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_BFD_H
diff --git a/lib/bitfield.h b/lib/bitfield.h
index 7062796a99..4ff9c7fb2e 100644
--- a/lib/bitfield.h
+++ b/lib/bitfield.h
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Quagga; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* A simple bit array implementation to allocate and free IDs. An example
diff --git a/lib/buffer.c b/lib/buffer.c
index 1dfcdb4732..649677fc93 100644
--- a/lib/buffer.c
+++ b/lib/buffer.c
@@ -8,16 +8,15 @@
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2, or (at your
* option) any later version.
- *
+ *
* GNU Zebra is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
diff --git a/lib/buffer.h b/lib/buffer.h
index 6c3dc76a1b..67ac71cad8 100644
--- a/lib/buffer.h
+++ b/lib/buffer.h
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_BUFFER_H
diff --git a/lib/command.c b/lib/command.c
index ff921ff402..84d59f076c 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -19,10 +19,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
@@ -40,15 +39,13 @@
#include "workqueue.h"
#include "vrf.h"
#include "command_match.h"
+#include "command_graph.h"
#include "qobj.h"
#include "defaults.h"
DEFINE_MTYPE( LIB, HOST, "Host config")
DEFINE_MTYPE( LIB, STRVEC, "String vector")
-DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command Tokens")
-DEFINE_MTYPE_STATIC(LIB, CMD_DESC, "Command Token Text")
-DEFINE_MTYPE_STATIC(LIB, CMD_TEXT, "Command Token Help")
-DEFINE_MTYPE( LIB, CMD_ARG, "Command Argument")
+DEFINE_MTYPE( LIB, COMPLETION, "Completion item")
/* Command vector which includes some level of command lists. Normally
each daemon maintains each own cmdvec. */
@@ -234,8 +231,8 @@ install_node (struct cmd_node *node,
node->cmdgraph = graph_new ();
node->cmd_vector = vector_init (VECTOR_MIN_SIZE);
// add start node
- struct cmd_token *token = new_cmd_token (START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
- graph_new_node (node->cmdgraph, token, (void (*)(void *)) &del_cmd_token);
+ struct cmd_token *token = cmd_token_new (START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
+ graph_new_node (node->cmdgraph, token, (void (*)(void *)) &cmd_token_del);
node->cmd_hash = hash_create (cmd_hash_key, cmd_hash_cmp);
}
@@ -306,272 +303,6 @@ cmd_prompt (enum node_type node)
return cnode->prompt;
}
-static bool
-cmd_nodes_link (struct graph_node *from, struct graph_node *to)
-{
- for (size_t i = 0; i < vector_active (from->to); i++)
- if (vector_slot (from->to, i) == to)
- return true;
- return false;
-}
-
-static bool cmd_nodes_equal (struct graph_node *ga, struct graph_node *gb);
-
-/* returns a single node to be excluded as "next" from iteration
- * - for JOIN_TKN, never continue back to the FORK_TKN
- * - in all other cases, don't try the node itself (in case of "...")
- */
-static inline struct graph_node *
-cmd_loopstop(struct graph_node *gn)
-{
- struct cmd_token *tok = gn->data;
- if (tok->type == JOIN_TKN)
- return tok->forkjoin;
- else
- return gn;
-}
-
-static bool
-cmd_subgraph_equal (struct graph_node *ga, struct graph_node *gb,
- struct graph_node *a_join)
-{
- size_t i, j;
- struct graph_node *a_fork, *b_fork;
- a_fork = cmd_loopstop (ga);
- b_fork = cmd_loopstop (gb);
-
- if (vector_active (ga->to) != vector_active (gb->to))
- return false;
- for (i = 0; i < vector_active (ga->to); i++)
- {
- struct graph_node *cga = vector_slot (ga->to, i);
-
- for (j = 0; j < vector_active (gb->to); j++)
- {
- struct graph_node *cgb = vector_slot (gb->to, i);
-
- if (cga == a_fork && cgb != b_fork)
- continue;
- if (cga == a_fork && cgb == b_fork)
- break;
-
- if (cmd_nodes_equal (cga, cgb))
- {
- if (cga == a_join)
- break;
- if (cmd_subgraph_equal (cga, cgb, a_join))
- break;
- }
- }
- if (j == vector_active (gb->to))
- return false;
- }
- return true;
-}
-
-/* deep compare -- for FORK_TKN, the entire subgraph is compared.
- * this is what's needed since we're not currently trying to partially
- * merge subgraphs */
-static bool
-cmd_nodes_equal (struct graph_node *ga, struct graph_node *gb)
-{
- struct cmd_token *a = ga->data, *b = gb->data;
-
- if (a->type != b->type || a->allowrepeat != b->allowrepeat)
- return false;
- if (a->type < SPECIAL_TKN && strcmp (a->text, b->text))
- return false;
- /* one a ..., the other not. */
- if (cmd_nodes_link (ga, ga) != cmd_nodes_link (gb, gb))
- return false;
-
- switch (a->type)
- {
- case RANGE_TKN:
- return a->min == b->min && a->max == b->max;
-
- case FORK_TKN:
- /* one is keywords, the other just option or selector ... */
- if (cmd_nodes_link (a->forkjoin, ga) != cmd_nodes_link (b->forkjoin, gb))
- return false;
- if (cmd_nodes_link (ga, a->forkjoin) != cmd_nodes_link (gb, b->forkjoin))
- return false;
- return cmd_subgraph_equal (ga, gb, a->forkjoin);
-
- default:
- return true;
- }
-}
-
-static void
-cmd_fork_bump_attr (struct graph_node *gn, struct graph_node *join,
- u_char attr)
-{
- size_t i;
- struct cmd_token *tok = gn->data;
- struct graph_node *stop = cmd_loopstop (gn);
-
- tok->attr = attr;
- for (i = 0; i < vector_active (gn->to); i++)
- {
- struct graph_node *next = vector_slot (gn->to, i);
- if (next == stop || next == join)
- continue;
- cmd_fork_bump_attr (next, join, attr);
- }
-}
-
-/* move an entire subtree from the temporary graph resulting from
- * parse() into the permanent graph for the command node.
- *
- * this touches rather deeply into the graph code unfortunately.
- */
-static void
-cmd_reparent_tree (struct graph *fromgraph, struct graph *tograph,
- struct graph_node *node)
-{
- struct graph_node *stop = cmd_loopstop (node);
- size_t i;
-
- for (i = 0; i < vector_active (fromgraph->nodes); i++)
- if (vector_slot (fromgraph->nodes, i) == node)
- {
- /* agressive iteration punching through subgraphs - may hit some
- * nodes twice. reparent only if found on old graph */
- vector_unset (fromgraph->nodes, i);
- vector_set (tograph->nodes, node);
- break;
- }
-
- for (i = 0; i < vector_active (node->to); i++)
- {
- struct graph_node *next = vector_slot (node->to, i);
- if (next != stop)
- cmd_reparent_tree (fromgraph, tograph, next);
- }
-}
-
-static void
-cmd_free_recur (struct graph *graph, struct graph_node *node,
- struct graph_node *stop)
-{
- struct graph_node *next, *nstop;
-
- for (size_t i = vector_active (node->to); i; i--)
- {
- next = vector_slot (node->to, i - 1);
- if (next == stop)
- continue;
- nstop = cmd_loopstop (next);
- if (nstop != next)
- cmd_free_recur (graph, next, nstop);
- cmd_free_recur (graph, nstop, stop);
- }
- graph_delete_node (graph, node);
-}
-
-static void
-cmd_free_node (struct graph *graph, struct graph_node *node)
-{
- struct cmd_token *tok = node->data;
- if (tok->type == JOIN_TKN)
- cmd_free_recur (graph, tok->forkjoin, node);
- graph_delete_node (graph, node);
-}
-
-/* recursive graph merge. call with
- * old ~= new
- * (which holds true for old == START_TKN, new == START_TKN)
- */
-static void
-cmd_merge_nodes (struct graph *oldgraph, struct graph *newgraph,
- struct graph_node *old, struct graph_node *new,
- int direction)
-{
- struct cmd_token *tok;
- struct graph_node *old_skip, *new_skip;
- old_skip = cmd_loopstop (old);
- new_skip = cmd_loopstop (new);
-
- assert (direction == 1 || direction == -1);
-
- tok = old->data;
- tok->refcnt += direction;
-
- size_t j, i;
- for (j = 0; j < vector_active (new->to); j++)
- {
- struct graph_node *cnew = vector_slot (new->to, j);
- if (cnew == new_skip)
- continue;
-
- for (i = 0; i < vector_active (old->to); i++)
- {
- struct graph_node *cold = vector_slot (old->to, i);
- if (cold == old_skip)
- continue;
-
- if (cmd_nodes_equal (cold, cnew))
- {
- struct cmd_token *told = cold->data, *tnew = cnew->data;
-
- if (told->type == END_TKN)
- {
- if (direction < 0)
- {
- graph_delete_node (oldgraph, vector_slot (cold->to, 0));
- graph_delete_node (oldgraph, cold);
- }
- else
- /* force no-match handling to install END_TKN */
- i = vector_active (old->to);
- break;
- }
-
- /* the entire fork compared as equal, we continue after it. */
- if (told->type == FORK_TKN)
- {
- if (tnew->attr < told->attr && direction > 0)
- cmd_fork_bump_attr (cold, told->forkjoin, tnew->attr);
- /* XXX: no reverse bump on uninstall */
- told = (cold = told->forkjoin)->data;
- tnew = (cnew = tnew->forkjoin)->data;
- }
- if (tnew->attr < told->attr)
- told->attr = tnew->attr;
-
- cmd_merge_nodes (oldgraph, newgraph, cold, cnew, direction);
- break;
- }
- }
- /* nothing found => add new to old */
- if (i == vector_active (old->to) && direction > 0)
- {
- assert (vector_count (cnew->from) ==
- cmd_nodes_link (cnew, cnew) ? 2 : 1);
- graph_remove_edge (new, cnew);
-
- cmd_reparent_tree (newgraph, oldgraph, cnew);
-
- graph_add_edge (old, cnew);
- }
- }
-
- if (!tok->refcnt)
- cmd_free_node (oldgraph, old);
-}
-
-void
-cmd_merge_graphs (struct graph *old, struct graph *new, int direction)
-{
- assert (vector_active (old->nodes) >= 1);
- assert (vector_active (new->nodes) >= 1);
-
- cmd_merge_nodes (old, new,
- vector_slot (old->nodes, 0), vector_slot (new->nodes, 0),
- direction);
-}
-
/* Install a command into a node. */
void
install_element (enum node_type ntype, struct cmd_element *cmd)
@@ -592,6 +323,7 @@ install_element (enum node_type ntype, struct cmd_element *cmd)
{
fprintf (stderr, "Command node %d doesn't exist, please check it\n",
ntype);
+ fprintf (stderr, "Have you called install_node before this install_element?\n");
exit (EXIT_FAILURE);
}
@@ -606,11 +338,12 @@ install_element (enum node_type ntype, struct cmd_element *cmd)
assert (hash_get (cnode->cmd_hash, cmd, hash_alloc_intern));
struct graph *graph = graph_new();
- struct cmd_token *token = new_cmd_token (START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
- graph_new_node (graph, token, (void (*)(void *)) &del_cmd_token);
+ struct cmd_token *token = cmd_token_new (START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
+ graph_new_node (graph, token, (void (*)(void *)) &cmd_token_del);
- command_parse_format (graph, cmd);
- cmd_merge_graphs (cnode->cmdgraph, graph, +1);
+ cmd_graph_parse (graph, cmd);
+ cmd_graph_names (graph);
+ cmd_graph_merge (cnode->cmdgraph, graph, +1);
graph_delete_graph (graph);
vector_set (cnode->cmd_vector, cmd);
@@ -638,6 +371,7 @@ uninstall_element (enum node_type ntype, struct cmd_element *cmd)
{
fprintf (stderr, "Command node %d doesn't exist, please check it\n",
ntype);
+ fprintf (stderr, "Have you called install_node before this install_element?\n");
exit (EXIT_FAILURE);
}
@@ -652,11 +386,12 @@ uninstall_element (enum node_type ntype, struct cmd_element *cmd)
vector_unset_value (cnode->cmd_vector, cmd);
struct graph *graph = graph_new();
- struct cmd_token *token = new_cmd_token (START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
- graph_new_node (graph, token, (void (*)(void *)) &del_cmd_token);
+ struct cmd_token *token = cmd_token_new (START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
+ graph_new_node (graph, token, (void (*)(void *)) &cmd_token_del);
- command_parse_format (graph, cmd);
- cmd_merge_graphs (cnode->cmdgraph, graph, -1);
+ cmd_graph_parse (graph, cmd);
+ cmd_graph_names (graph);
+ cmd_graph_merge (cnode->cmdgraph, graph, -1);
graph_delete_graph (graph);
if (ntype == VIEW_NODE)
@@ -945,6 +680,86 @@ cmd_describe_command (vector vline, struct vty *vty, int *status)
return cmd_complete_command_real (vline, vty, status);
}
+static struct list *varhandlers = NULL;
+
+void
+cmd_variable_complete (struct cmd_token *token, const char *arg, vector comps)
+{
+ struct listnode *ln;
+ const struct cmd_variable_handler *cvh;
+ size_t i, argsz;
+ vector tmpcomps;
+
+ tmpcomps = arg ? vector_init (VECTOR_MIN_SIZE) : comps;
+
+ for (ALL_LIST_ELEMENTS_RO(varhandlers, ln, cvh))
+ {
+ if (cvh->tokenname && strcmp(cvh->tokenname, token->text))
+ continue;
+ if (cvh->varname && (!token->varname || strcmp(cvh->varname, token->varname)))
+ continue;
+ cvh->completions(tmpcomps, token);
+ break;
+ }
+
+ if (!arg)
+ return;
+
+ argsz = strlen(arg);
+ for (i = vector_active(tmpcomps); i; i--)
+ {
+ char *item = vector_slot(tmpcomps, i - 1);
+ if (strlen(item) >= argsz
+ && !strncmp(item, arg, argsz))
+ vector_set(comps, item);
+ else
+ XFREE(MTYPE_COMPLETION, item);
+ }
+ vector_free(tmpcomps);
+}
+
+void
+cmd_variable_handler_register (const struct cmd_variable_handler *cvh)
+{
+ if (!varhandlers)
+ return;
+
+ for (; cvh->completions; cvh++)
+ listnode_add(varhandlers, (void *)cvh);
+}
+
+DEFUN_HIDDEN (autocomplete,
+ autocomplete_cmd,
+ "autocomplete TYPE TEXT VARNAME",
+ "Autocompletion handler (internal, for vtysh)\n"
+ "cmd_token->type\n"
+ "cmd_token->text\n"
+ "cmd_token->varname\n")
+{
+ struct cmd_token tok;
+ vector comps = vector_init(32);
+ size_t i;
+
+ memset(&tok, 0, sizeof(tok));
+ tok.type = atoi(argv[1]->arg);
+ tok.text = argv[2]->arg;
+ tok.varname = argv[3]->arg;
+ if (!strcmp(tok.varname, "-"))
+ tok.varname = NULL;
+
+ cmd_variable_complete(&tok, NULL, comps);
+
+ for (i = 0; i < vector_active(comps); i++)
+ {
+ char *text = vector_slot(comps, i);
+ vty_out(vty, "%s\n", text);
+ XFREE(MTYPE_COMPLETION, text);
+ }
+
+ vector_free(comps);
+ return CMD_SUCCESS;
+}
+
/**
* Generate possible tab-completions for the given input. This function only
* returns results that would result in a valid command if used as Readline
@@ -986,7 +801,12 @@ cmd_complete_command (vector vline, struct vty *vty, int *status)
{
struct cmd_token *token = vector_slot (initial_comps, i);
if (token->type == WORD_TKN)
- vector_set (comps, token);
+ vector_set (comps, XSTRDUP (MTYPE_COMPLETION, token->text));
+ else if (IS_VARYING_TOKEN(token->type))
+ {
+ const char *ref = vector_lookup(vline, vector_active (vline) - 1);
+ cmd_variable_complete (token, ref, comps);
+ }
}
vector_free (initial_comps);
@@ -1008,9 +828,7 @@ cmd_complete_command (vector vline, struct vty *vty, int *status)
unsigned int i;
for (i = 0; i < vector_active (comps); i++)
{
- struct cmd_token *token = vector_slot (comps, i);
- ret[i] = XSTRDUP (MTYPE_TMP, token->text);
- vector_unset (comps, i);
+ ret[i] = vector_slot (comps, i);
}
// set the last element to NULL, because this array is used in
// a Readline completion_generator function which expects NULL
@@ -1055,9 +873,11 @@ node_parent ( enum node_type node )
case BGP_VNC_L2_GROUP_NODE:
case BGP_IPV4_NODE:
case BGP_IPV4M_NODE:
+ case BGP_IPV4L_NODE:
case BGP_IPV6_NODE:
case BGP_IPV6M_NODE:
case BGP_EVPN_NODE:
+ case BGP_IPV6L_NODE:
ret = BGP_NODE;
break;
case KEYCHAIN_KEY_NODE:
@@ -1399,6 +1219,7 @@ cmd_exit (struct vty *vty)
case ZEBRA_NODE:
case BGP_NODE:
case RIP_NODE:
+ case EIGRP_NODE:
case RIPNG_NODE:
case OSPF_NODE:
case OSPF6_NODE:
@@ -1414,6 +1235,7 @@ cmd_exit (struct vty *vty)
break;
case BGP_IPV4_NODE:
case BGP_IPV4M_NODE:
+ case BGP_IPV4L_NODE:
case BGP_VPNV4_NODE:
case BGP_VPNV6_NODE:
case BGP_ENCAP_NODE:
@@ -1425,6 +1247,7 @@ cmd_exit (struct vty *vty)
case BGP_IPV6_NODE:
case BGP_IPV6M_NODE:
case BGP_EVPN_NODE:
+ case BGP_IPV6L_NODE:
vty->node = BGP_NODE;
break;
case LDP_IPV4_NODE:
@@ -1480,6 +1303,7 @@ DEFUN (config_end,
case ZEBRA_NODE:
case RIP_NODE:
case RIPNG_NODE:
+ case EIGRP_NODE:
case BGP_NODE:
case BGP_ENCAP_NODE:
case BGP_ENCAPV6_NODE:
@@ -1491,9 +1315,11 @@ DEFUN (config_end,
case BGP_VPNV6_NODE:
case BGP_IPV4_NODE:
case BGP_IPV4M_NODE:
+ case BGP_IPV4L_NODE:
case BGP_IPV6_NODE:
case BGP_IPV6M_NODE:
case BGP_EVPN_NODE:
+ case BGP_IPV6L_NODE:
case RMAP_NODE:
case OSPF_NODE:
case OSPF6_NODE:
@@ -1546,11 +1372,6 @@ DEFUN (frr_version_defaults,
"set of configuration defaults used\n"
"version string\n")
{
- if (vty->type == VTY_TERM || vty->type == VTY_SHELL)
- /* only print this when the user tries to do run it */
- vty_out (vty, "%% NOTE: This command currently does nothing.%s"
- "%% It is written to the configuration for future reference.%s",
- VTY_NEWLINE, VTY_NEWLINE);
return CMD_SUCCESS;
}
@@ -2109,16 +1930,8 @@ DEFUN (config_terminal_length,
"Number of lines on screen (0 for no pausing)\n")
{
int idx_number = 2;
- int lines;
- char *endptr = NULL;
- lines = strtol (argv[idx_number]->arg, &endptr, 10);
- if (lines < 0 || lines > 512 || *endptr != '\0')
- {
- vty_out (vty, "length is malformed%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- vty->lines = lines;
+ vty->lines = atoi (argv[idx_number]->arg);
return CMD_SUCCESS;
}
@@ -2142,16 +1955,8 @@ DEFUN (service_terminal_length,
"Number of lines of VTY (0 means no line control)\n")
{
int idx_number = 2;
- int lines;
- char *endptr = NULL;
- lines = strtol (argv[idx_number]->arg, &endptr, 10);
- if (lines < 0 || lines > 512 || *endptr != '\0')
- {
- vty_out (vty, "length is malformed%s", VTY_NEWLINE);
- return CMD_WARNING;
- }
- host.lines = lines;
+ host.lines = atoi (argv[idx_number]->arg);
return CMD_SUCCESS;
}
@@ -2657,6 +2462,8 @@ install_default (enum node_type node)
install_element (node, &config_write_cmd);
install_element (node, &show_running_config_cmd);
+
+ install_element (node, &autocomplete_cmd);
}
/* Initialize command interface. Install basic nodes and commands.
@@ -2669,6 +2476,8 @@ cmd_init (int terminal)
{
qobj_init ();
+ varhandlers = list_new ();
+
/* Allocate initial top vector of commands. */
cmdvec = vector_init (VECTOR_MIN_SIZE);
@@ -2704,6 +2513,7 @@ cmd_init (int terminal)
install_element (VIEW_NODE, &show_logging_cmd);
install_element (VIEW_NODE, &show_commandtree_cmd);
install_element (VIEW_NODE, &echo_cmd);
+ install_element (VIEW_NODE, &autocomplete_cmd);
}
if (terminal)
@@ -2768,50 +2578,6 @@ cmd_init (int terminal)
#endif
}
-struct cmd_token *
-new_cmd_token (enum cmd_token_type type, u_char attr,
- const char *text, const char *desc)
-{
- struct cmd_token *token = XCALLOC (MTYPE_CMD_TOKENS, sizeof (struct cmd_token));
- token->type = type;
- token->attr = attr;
- token->text = text ? XSTRDUP (MTYPE_CMD_TEXT, text) : NULL;
- token->desc = desc ? XSTRDUP (MTYPE_CMD_DESC, desc) : NULL;
- token->refcnt = 1;
- token->arg = NULL;
- token->allowrepeat = false;
-
- return token;
-}
-
-void
-del_cmd_token (struct cmd_token *token)
-{
- if (!token) return;
-
- if (token->text)
- XFREE (MTYPE_CMD_TEXT, token->text);
- if (token->desc)
- XFREE (MTYPE_CMD_DESC, token->desc);
- if (token->arg)
- XFREE (MTYPE_CMD_ARG, token->arg);
-
- XFREE (MTYPE_CMD_TOKENS, token);
-}
-
-struct cmd_token *
-copy_cmd_token (struct cmd_token *token)
-{
- struct cmd_token *copy = new_cmd_token (token->type, token->attr, NULL, NULL);
- copy->max = token->max;
- copy->min = token->min;
- copy->text = token->text ? XSTRDUP (MTYPE_CMD_TEXT, token->text) : NULL;
- copy->desc = token->desc ? XSTRDUP (MTYPE_CMD_DESC, token->desc) : NULL;
- copy->arg = token->arg ? XSTRDUP (MTYPE_CMD_ARG, token->arg) : NULL;
-
- return copy;
-}
-
void
cmd_terminate ()
{
diff --git a/lib/command.h b/lib/command.h
index d62f7655ee..35fb20f8b0 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_COMMAND_H
@@ -29,9 +28,10 @@
#include "graph.h"
#include "memory.h"
#include "hash.h"
+#include "command_graph.h"
DECLARE_MTYPE(HOST)
-DECLARE_MTYPE(CMD_ARG)
+DECLARE_MTYPE(COMPLETION)
/* for test-commands.c */
DECLARE_MTYPE(STRVEC)
@@ -91,13 +91,16 @@ enum node_type
TABLE_NODE, /* rtm_table selection node. */
RIP_NODE, /* RIP protocol mode node. */
RIPNG_NODE, /* RIPng protocol mode node. */
+ EIGRP_NODE, /* EIGRP protocol mode node. */
BGP_NODE, /* BGP protocol mode which includes BGP4+ */
BGP_VPNV4_NODE, /* BGP MPLS-VPN PE exchange. */
BGP_VPNV6_NODE, /* BGP MPLS-VPN PE exchange. */
BGP_IPV4_NODE, /* BGP IPv4 unicast address family. */
BGP_IPV4M_NODE, /* BGP IPv4 multicast address family. */
+ BGP_IPV4L_NODE, /* BGP IPv4 labeled unicast address family. */
BGP_IPV6_NODE, /* BGP IPv6 address family */
BGP_IPV6M_NODE, /* BGP IPv6 multicast address family. */
+ BGP_IPV6L_NODE, /* BGP IPv6 labeled unicast address family. */
BGP_ENCAP_NODE, /* BGP ENCAP SAFI */
BGP_ENCAPV6_NODE, /* BGP ENCAP SAFI */
BGP_VRF_POLICY_NODE, /* BGP VRF policy */
@@ -162,69 +165,6 @@ struct cmd_node
struct hash *cmd_hash;
};
-/**
- * Types for tokens.
- *
- * The type determines what kind of data the token can match (in the
- * matching use case) or hold (in the argv use case).
- */
-enum cmd_token_type
-{
- WORD_TKN, // words
- VARIABLE_TKN, // almost anything
- RANGE_TKN, // integer range
- IPV4_TKN, // IPV4 addresses
- IPV4_PREFIX_TKN, // IPV4 network prefixes
- IPV6_TKN, // IPV6 prefixes
- IPV6_PREFIX_TKN, // IPV6 network prefixes
-
- /* plumbing types */
- FORK_TKN, // marks subgraph beginning
- JOIN_TKN, // marks subgraph end
- START_TKN, // first token in line
- END_TKN, // last token in line
-
- SPECIAL_TKN = FORK_TKN,
-};
-
-/* Command attributes */
-enum
-{
- CMD_ATTR_NORMAL,
- CMD_ATTR_DEPRECATED,
- CMD_ATTR_HIDDEN,
-};
-
-/* Comamand token struct. */
-struct cmd_token
-{
- enum cmd_token_type type; // token type
- u_char attr; // token attributes
- bool allowrepeat; // matcher allowed to match token repetively?
- uint32_t refcnt;
-
- char *text; // token text
- char *desc; // token description
- long long min, max; // for ranges
- char *arg; // user input that matches this token
-
- struct graph_node *forkjoin; // paired FORK/JOIN for JOIN/FORK
-};
-
-/* Structure of command element. */
-struct cmd_element
-{
- const char *string; /* Command specification by string. */
- const char *doc; /* Documentation of this command. */
- int daemon; /* Daemon to which this command belong. */
- u_char attr; /* Command attributes */
-
- /* handler function for command */
- int (*func) (const struct cmd_element *, struct vty *, int, struct cmd_token *[]);
-
- const char *name; /* symbol name for debugging */
-};
-
/* Return value of the commands. */
#define CMD_SUCCESS 0
#define CMD_WARNING 1
@@ -356,6 +296,7 @@ struct cmd_element
#define REDIST_STR "Redistribute information from another routing protocol\n"
#define CLEAR_STR "Reset functions\n"
#define RIP_STR "RIP information\n"
+#define EIGRP_STR "EIGRP information\n"
#define BGP_STR "BGP information\n"
#define BGP_SOFT_STR "Soft reconfig inbound and outbound updates\n"
#define BGP_SOFT_IN_STR "Send route-refresh unless using 'soft-reconfiguration inbound'\n"
@@ -437,15 +378,7 @@ extern int cmd_hostname_set (const char *hostname);
/* NOT safe for general use; call this only if DEV_BUILD! */
extern void grammar_sandbox_init (void);
-/* memory management for cmd_token */
-extern struct cmd_token *new_cmd_token (enum cmd_token_type, u_char attr,
- const char *text, const char *desc);
-extern void del_cmd_token (struct cmd_token *);
-extern struct cmd_token *copy_cmd_token (struct cmd_token *);
-
extern vector completions_to_vec (struct list *completions);
-extern void cmd_merge_graphs (struct graph *old, struct graph *new, int direction);
-extern void command_parse_format (struct graph *graph, struct cmd_element *cmd);
/* Export typical functions. */
extern const char *host_config_get (void);
@@ -458,7 +391,12 @@ extern int cmd_banner_motd_file (const char *);
/* struct host global, ick */
extern struct host host;
-/* text for <cr> command */
-#define CMD_CR_TEXT "<cr>"
+struct cmd_variable_handler {
+ const char *tokenname, *varname;
+ void (*completions)(vector out, struct cmd_token *token);
+};
+
+extern void cmd_variable_complete (struct cmd_token *token, const char *arg, vector comps);
+extern void cmd_variable_handler_register (const struct cmd_variable_handler *cvh);
#endif /* _ZEBRA_COMMAND_H */
diff --git a/lib/command_graph.c b/lib/command_graph.c
new file mode 100644
index 0000000000..8cfb333575
--- /dev/null
+++ b/lib/command_graph.c
@@ -0,0 +1,478 @@
+/*
+ * CLI graph handling
+ *
+ * --
+ * Copyright (C) 2016 Cumulus Networks, Inc.
+ * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
+ * Copyright (C) 2013 by Open Source Routing.
+ * Copyright (C) 2013 by Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <zebra.h>
+
+#include "command_graph.h"
+
+DEFINE_MTYPE_STATIC(LIB, CMD_TOKENS, "Command Tokens")
+DEFINE_MTYPE_STATIC(LIB, CMD_DESC, "Command Token Text")
+DEFINE_MTYPE_STATIC(LIB, CMD_TEXT, "Command Token Help")
+DEFINE_MTYPE( LIB, CMD_ARG, "Command Argument")
+DEFINE_MTYPE_STATIC(LIB, CMD_VAR, "Command Argument Name")
+
+struct cmd_token *
+cmd_token_new (enum cmd_token_type type, u_char attr,
+ const char *text, const char *desc)
+{
+ struct cmd_token *token = XCALLOC (MTYPE_CMD_TOKENS, sizeof (struct cmd_token));
+ token->type = type;
+ token->attr = attr;
+ token->text = text ? XSTRDUP (MTYPE_CMD_TEXT, text) : NULL;
+ token->desc = desc ? XSTRDUP (MTYPE_CMD_DESC, desc) : NULL;
+ token->refcnt = 1;
+ token->arg = NULL;
+ token->allowrepeat = false;
+ token->varname = NULL;
+
+ return token;
+}
+
+void
+cmd_token_del (struct cmd_token *token)
+{
+ if (!token) return;
+
+ XFREE (MTYPE_CMD_TEXT, token->text);
+ XFREE (MTYPE_CMD_DESC, token->desc);
+ XFREE (MTYPE_CMD_ARG, token->arg);
+ XFREE (MTYPE_CMD_VAR, token->varname);
+
+ XFREE (MTYPE_CMD_TOKENS, token);
+}
+
+struct cmd_token *
+cmd_token_dup (struct cmd_token *token)
+{
+ struct cmd_token *copy = cmd_token_new (token->type, token->attr, NULL, NULL);
+ copy->max = token->max;
+ copy->min = token->min;
+ copy->text = token->text ? XSTRDUP (MTYPE_CMD_TEXT, token->text) : NULL;
+ copy->desc = token->desc ? XSTRDUP (MTYPE_CMD_DESC, token->desc) : NULL;
+ copy->arg = token->arg ? XSTRDUP (MTYPE_CMD_ARG, token->arg) : NULL;
+ copy->varname = token->varname ? XSTRDUP (MTYPE_CMD_VAR, token->varname) : NULL;
+
+ return copy;
+}
+
+void cmd_token_varname_set(struct cmd_token *token, const char *varname)
+{
+ XFREE (MTYPE_CMD_VAR, token->varname);
+ if (!varname)
+ {
+ token->varname = NULL;
+ return;
+ }
+
+ size_t len = strlen (varname), i;
+ token->varname = XMALLOC (MTYPE_CMD_VAR, len + 1);
+
+ for (i = 0; i < len; i++)
+ switch (varname[i])
+ {
+ case '-':
+ case '+':
+ case '*':
+ case ':':
+ token->varname[i] = '_';
+ break;
+ default:
+ token->varname[i] = tolower (varname[i]);
+ }
+ token->varname[len] = '\0';
+}
+
+static bool
+cmd_nodes_link (struct graph_node *from, struct graph_node *to)
+{
+ for (size_t i = 0; i < vector_active (from->to); i++)
+ if (vector_slot (from->to, i) == to)
+ return true;
+ return false;
+}
+
+static bool cmd_nodes_equal (struct graph_node *ga, struct graph_node *gb);
+
+/* returns a single node to be excluded as "next" from iteration
+ * - for JOIN_TKN, never continue back to the FORK_TKN
+ * - in all other cases, don't try the node itself (in case of "...")
+ */
+static inline struct graph_node *
+cmd_loopstop(struct graph_node *gn)
+{
+ struct cmd_token *tok = gn->data;
+ if (tok->type == JOIN_TKN)
+ return tok->forkjoin;
+ else
+ return gn;
+}
+
+static bool
+cmd_subgraph_equal (struct graph_node *ga, struct graph_node *gb,
+ struct graph_node *a_join)
+{
+ size_t i, j;
+ struct graph_node *a_fork, *b_fork;
+ a_fork = cmd_loopstop (ga);
+ b_fork = cmd_loopstop (gb);
+
+ if (vector_active (ga->to) != vector_active (gb->to))
+ return false;
+ for (i = 0; i < vector_active (ga->to); i++)
+ {
+ struct graph_node *cga = vector_slot (ga->to, i);
+
+ for (j = 0; j < vector_active (gb->to); j++)
+ {
+ struct graph_node *cgb = vector_slot (gb->to, i);
+
+ if (cga == a_fork && cgb != b_fork)
+ continue;
+ if (cga == a_fork && cgb == b_fork)
+ break;
+
+ if (cmd_nodes_equal (cga, cgb))
+ {
+ if (cga == a_join)
+ break;
+ if (cmd_subgraph_equal (cga, cgb, a_join))
+ break;
+ }
+ }
+ if (j == vector_active (gb->to))
+ return false;
+ }
+ return true;
+}
+
+/* deep compare -- for FORK_TKN, the entire subgraph is compared.
+ * this is what's needed since we're not currently trying to partially
+ * merge subgraphs */
+static bool
+cmd_nodes_equal (struct graph_node *ga, struct graph_node *gb)
+{
+ struct cmd_token *a = ga->data, *b = gb->data;
+
+ if (a->type != b->type || a->allowrepeat != b->allowrepeat)
+ return false;
+ if (a->type < SPECIAL_TKN && strcmp (a->text, b->text))
+ return false;
+ /* one a ..., the other not. */
+ if (cmd_nodes_link (ga, ga) != cmd_nodes_link (gb, gb))
+ return false;
+ if (!a->varname != !b->varname)
+ return false;
+ if (a->varname && strcmp (a->varname, b->varname))
+ return false;
+
+ switch (a->type)
+ {
+ case RANGE_TKN:
+ return a->min == b->min && a->max == b->max;
+
+ case FORK_TKN:
+ /* one is keywords, the other just option or selector ... */
+ if (cmd_nodes_link (a->forkjoin, ga) != cmd_nodes_link (b->forkjoin, gb))
+ return false;
+ if (cmd_nodes_link (ga, a->forkjoin) != cmd_nodes_link (gb, b->forkjoin))
+ return false;
+ return cmd_subgraph_equal (ga, gb, a->forkjoin);
+
+ default:
+ return true;
+ }
+}
+
+static void
+cmd_fork_bump_attr (struct graph_node *gn, struct graph_node *join,
+ u_char attr)
+{
+ size_t i;
+ struct cmd_token *tok = gn->data;
+ struct graph_node *stop = cmd_loopstop (gn);
+
+ tok->attr = attr;
+ for (i = 0; i < vector_active (gn->to); i++)
+ {
+ struct graph_node *next = vector_slot (gn->to, i);
+ if (next == stop || next == join)
+ continue;
+ cmd_fork_bump_attr (next, join, attr);
+ }
+}
+
+/* move an entire subtree from the temporary graph resulting from
+ * parse() into the permanent graph for the command node.
+ *
+ * this touches rather deeply into the graph code unfortunately.
+ */
+static void
+cmd_reparent_tree (struct graph *fromgraph, struct graph *tograph,
+ struct graph_node *node)
+{
+ struct graph_node *stop = cmd_loopstop (node);
+ size_t i;
+
+ for (i = 0; i < vector_active (fromgraph->nodes); i++)
+ if (vector_slot (fromgraph->nodes, i) == node)
+ {
+ /* agressive iteration punching through subgraphs - may hit some
+ * nodes twice. reparent only if found on old graph */
+ vector_unset (fromgraph->nodes, i);
+ vector_set (tograph->nodes, node);
+ break;
+ }
+
+ for (i = 0; i < vector_active (node->to); i++)
+ {
+ struct graph_node *next = vector_slot (node->to, i);
+ if (next != stop)
+ cmd_reparent_tree (fromgraph, tograph, next);
+ }
+}
+
+static void
+cmd_free_recur (struct graph *graph, struct graph_node *node,
+ struct graph_node *stop)
+{
+ struct graph_node *next, *nstop;
+
+ for (size_t i = vector_active (node->to); i; i--)
+ {
+ next = vector_slot (node->to, i - 1);
+ if (next == stop)
+ continue;
+ nstop = cmd_loopstop (next);
+ if (nstop != next)
+ cmd_free_recur (graph, next, nstop);
+ cmd_free_recur (graph, nstop, stop);
+ }
+ graph_delete_node (graph, node);
+}
+
+static void
+cmd_free_node (struct graph *graph, struct graph_node *node)
+{
+ struct cmd_token *tok = node->data;
+ if (tok->type == JOIN_TKN)
+ cmd_free_recur (graph, tok->forkjoin, node);
+ graph_delete_node (graph, node);
+}
+
+/* recursive graph merge. call with
+ * old ~= new
+ * (which holds true for old == START_TKN, new == START_TKN)
+ */
+static void
+cmd_merge_nodes (struct graph *oldgraph, struct graph *newgraph,
+ struct graph_node *old, struct graph_node *new,
+ int direction)
+{
+ struct cmd_token *tok;
+ struct graph_node *old_skip, *new_skip;
+ old_skip = cmd_loopstop (old);
+ new_skip = cmd_loopstop (new);
+
+ assert (direction == 1 || direction == -1);
+
+ tok = old->data;
+ tok->refcnt += direction;
+
+ size_t j, i;
+ for (j = 0; j < vector_active (new->to); j++)
+ {
+ struct graph_node *cnew = vector_slot (new->to, j);
+ if (cnew == new_skip)
+ continue;
+
+ for (i = 0; i < vector_active (old->to); i++)
+ {
+ struct graph_node *cold = vector_slot (old->to, i);
+ if (cold == old_skip)
+ continue;
+
+ if (cmd_nodes_equal (cold, cnew))
+ {
+ struct cmd_token *told = cold->data, *tnew = cnew->data;
+
+ if (told->type == END_TKN)
+ {
+ if (direction < 0)
+ {
+ graph_delete_node (oldgraph, vector_slot (cold->to, 0));
+ graph_delete_node (oldgraph, cold);
+ }
+ else
+ /* force no-match handling to install END_TKN */
+ i = vector_active (old->to);
+ break;
+ }
+
+ /* the entire fork compared as equal, we continue after it. */
+ if (told->type == FORK_TKN)
+ {
+ if (tnew->attr < told->attr && direction > 0)
+ cmd_fork_bump_attr (cold, told->forkjoin, tnew->attr);
+ /* XXX: no reverse bump on uninstall */
+ told = (cold = told->forkjoin)->data;
+ tnew = (cnew = tnew->forkjoin)->data;
+ }
+ if (tnew->attr < told->attr)
+ told->attr = tnew->attr;
+
+ cmd_merge_nodes (oldgraph, newgraph, cold, cnew, direction);
+ break;
+ }
+ }
+ /* nothing found => add new to old */
+ if (i == vector_active (old->to) && direction > 0)
+ {
+ assert (vector_count (cnew->from) ==
+ cmd_nodes_link (cnew, cnew) ? 2 : 1);
+ graph_remove_edge (new, cnew);
+
+ cmd_reparent_tree (newgraph, oldgraph, cnew);
+
+ graph_add_edge (old, cnew);
+ }
+ }
+
+ if (!tok->refcnt)
+ cmd_free_node (oldgraph, old);
+}
+
+void
+cmd_graph_merge (struct graph *old, struct graph *new, int direction)
+{
+ assert (vector_active (old->nodes) >= 1);
+ assert (vector_active (new->nodes) >= 1);
+
+ cmd_merge_nodes (old, new,
+ vector_slot (old->nodes, 0), vector_slot (new->nodes, 0),
+ direction);
+}
+
+static void
+cmd_node_names (struct graph_node *gn, struct graph_node *join,
+ const char *prevname)
+{
+ size_t i;
+ struct cmd_token *tok = gn->data, *jointok;
+ struct graph_node *stop = cmd_loopstop (gn);
+
+ switch (tok->type)
+ {
+ case WORD_TKN:
+ prevname = tok->text;
+ break;
+
+ case VARIABLE_TKN:
+ if (!tok->varname
+ && strcmp (tok->text, "WORD")
+ && strcmp (tok->text, "NAME"))
+ cmd_token_varname_set (tok, tok->text);
+ /* fallthrough */
+ case RANGE_TKN:
+ case IPV4_TKN:
+ case IPV4_PREFIX_TKN:
+ case IPV6_TKN:
+ case IPV6_PREFIX_TKN:
+ if (!tok->varname && prevname)
+ cmd_token_varname_set (tok, prevname);
+ prevname = NULL;
+ break;
+
+ case START_TKN:
+ case END_TKN:
+ case JOIN_TKN:
+ /* "<foo|bar> WORD" -> word is not "bar" or "foo" */
+ prevname = NULL;
+ break;
+
+ case FORK_TKN:
+ /* apply "<A.B.C.D|X:X::X:X>$name" */
+ jointok = tok->forkjoin->data;
+ if (!jointok->varname)
+ break;
+ for (i = 0; i < vector_active (tok->forkjoin->from); i++)
+ {
+ struct graph_node *tail = vector_slot (tok->forkjoin->from, i);
+ struct cmd_token *tailtok = tail->data;
+ if (tail == gn || tailtok->varname)
+ continue;
+ cmd_token_varname_set (tailtok, jointok->varname);
+ }
+ break;
+ }
+
+ for (i = 0; i < vector_active (gn->to); i++)
+ {
+ struct graph_node *next = vector_slot (gn->to, i);
+ if (next == stop || next == join)
+ continue;
+ cmd_node_names (next, join, prevname);
+ }
+
+ if (tok->type == FORK_TKN && tok->forkjoin != join)
+ cmd_node_names (tok->forkjoin, join, NULL);
+}
+
+void
+cmd_graph_names (struct graph *graph)
+{
+ struct graph_node *start;
+
+ assert (vector_active (graph->nodes) >= 1);
+ start = vector_slot (graph->nodes, 0);
+
+ /* apply varname on initial "[no]" */
+ do
+ {
+ if (vector_active (start->to) != 1)
+ break;
+
+ struct graph_node *first = vector_slot (start->to, 0);
+ struct cmd_token *tok = first->data;
+ /* looking for an option with 2 choices, nothing or "no" */
+ if (tok->type != FORK_TKN || vector_active (first->to) != 2)
+ break;
+
+ struct graph_node *next0 = vector_slot (first->to, 0);
+ struct graph_node *next1 = vector_slot (first->to, 1);
+ /* one needs to be empty */
+ if (next0 != tok->forkjoin && next1 != tok->forkjoin)
+ break;
+
+ struct cmd_token *tok0 = next0->data;
+ struct cmd_token *tok1 = next1->data;
+ /* the other one needs to be "no" (only one will match here) */
+ if ((tok0->type == WORD_TKN && !strcmp(tok0->text, "no")))
+ cmd_token_varname_set (tok0, "no");
+ if ((tok1->type == WORD_TKN && !strcmp(tok1->text, "no")))
+ cmd_token_varname_set (tok1, "no");
+ }
+ while (0);
+
+ cmd_node_names (start, NULL, NULL);
+}
diff --git a/lib/command_graph.h b/lib/command_graph.h
new file mode 100644
index 0000000000..a7a34a0598
--- /dev/null
+++ b/lib/command_graph.h
@@ -0,0 +1,119 @@
+/*
+ * CLI graph handling
+ *
+ * --
+ * Copyright (C) 2016 Cumulus Networks, Inc.
+ * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
+ * Copyright (C) 2013 by Open Source Routing.
+ * Copyright (C) 2013 by Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _FRR_COMMAND_GRAPH_H
+#define _FRR_COMMAND_GRAPH_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "memory.h"
+#include "vector.h"
+#include "graph.h"
+
+DECLARE_MTYPE(CMD_ARG)
+
+struct vty;
+
+/**
+ * Types for tokens.
+ *
+ * The type determines what kind of data the token can match (in the
+ * matching use case) or hold (in the argv use case).
+ */
+enum cmd_token_type
+{
+ WORD_TKN, // words
+ VARIABLE_TKN, // almost anything
+ RANGE_TKN, // integer range
+ IPV4_TKN, // IPV4 addresses
+ IPV4_PREFIX_TKN, // IPV4 network prefixes
+ IPV6_TKN, // IPV6 prefixes
+ IPV6_PREFIX_TKN, // IPV6 network prefixes
+
+ /* plumbing types */
+ FORK_TKN, // marks subgraph beginning
+ JOIN_TKN, // marks subgraph end
+ START_TKN, // first token in line
+ END_TKN, // last token in line
+
+ SPECIAL_TKN = FORK_TKN,
+};
+
+#define IS_VARYING_TOKEN(x) ((x) >= VARIABLE_TKN && (x) < FORK_TKN)
+
+/* Command attributes */
+enum
+{
+ CMD_ATTR_NORMAL,
+ CMD_ATTR_DEPRECATED,
+ CMD_ATTR_HIDDEN,
+};
+
+/* Comamand token struct. */
+struct cmd_token
+{
+ enum cmd_token_type type; // token type
+ uint8_t attr; // token attributes
+ bool allowrepeat; // matcher allowed to match token repetively?
+ uint32_t refcnt;
+
+ char *text; // token text
+ char *desc; // token description
+ long long min, max; // for ranges
+ char *arg; // user input that matches this token
+ char *varname;
+
+ struct graph_node *forkjoin; // paired FORK/JOIN for JOIN/FORK
+};
+
+/* Structure of command element. */
+struct cmd_element
+{
+ const char *string; /* Command specification by string. */
+ const char *doc; /* Documentation of this command. */
+ int daemon; /* Daemon to which this command belong. */
+ uint8_t attr; /* Command attributes */
+
+ /* handler function for command */
+ int (*func) (const struct cmd_element *, struct vty *, int, struct cmd_token *[]);
+
+ const char *name; /* symbol name for debugging */
+};
+
+/* text for <cr> command */
+#define CMD_CR_TEXT "<cr>"
+
+/* memory management for cmd_token */
+extern struct cmd_token *cmd_token_new (enum cmd_token_type, uint8_t attr,
+ const char *text, const char *desc);
+extern struct cmd_token *cmd_token_dup (struct cmd_token *);
+extern void cmd_token_del (struct cmd_token *);
+extern void cmd_token_varname_set(struct cmd_token *token, const char *varname);
+
+extern void cmd_graph_parse (struct graph *graph, struct cmd_element *cmd);
+extern void cmd_graph_names (struct graph *graph);
+extern void cmd_graph_merge (struct graph *old, struct graph *new, int direction);
+
+#endif /* _FRR_COMMAND_GRAPH_H */
diff --git a/lib/command_lex.l b/lib/command_lex.l
index deec1757c2..c020d193a1 100644
--- a/lib/command_lex.l
+++ b/lib/command_lex.l
@@ -23,6 +23,9 @@
*/
%{
+/* ignore harmless bug in old versions of flex */
+#pragma GCC diagnostic ignored "-Wsign-compare"
+
#include "command_parse.h"
#define YY_USER_ACTION yylloc->last_column += yyleng;
diff --git a/lib/command_match.c b/lib/command_match.c
index bbd9cd091d..75d8fdc3d3 100644
--- a/lib/command_match.c
+++ b/lib/command_match.c
@@ -16,10 +16,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
@@ -78,10 +77,7 @@ static enum match_type
match_ipv4_prefix (const char *);
static enum match_type
-match_ipv6 (const char *);
-
-static enum match_type
-match_ipv6_prefix (const char *);
+match_ipv6_prefix (const char *, bool);
static enum match_type
match_range (struct cmd_token *, const char *);
@@ -117,7 +113,7 @@ command_match (struct graph *cmdgraph,
struct listnode *tail = listtail (*argv);
// delete dummy start node
- del_cmd_token ((struct cmd_token *) head->data);
+ cmd_token_del ((struct cmd_token *) head->data);
list_delete_node (*argv, head);
// get cmd_element out of list tail
@@ -281,7 +277,7 @@ command_match_r (struct graph_node *start, vector vline, unsigned int n,
// manually deleted
struct cmd_element *el = leaf->data;
listnode_add (currbest, el);
- currbest->del = (void (*)(void *)) &del_cmd_token;
+ currbest->del = (void (*)(void *)) &cmd_token_del;
// do not break immediately; continue walking through the follow set
// to ensure that there is exactly one END_TKN
}
@@ -320,7 +316,7 @@ command_match_r (struct graph_node *start, vector vline, unsigned int n,
{
// copy token, set arg and prepend to currbest
struct cmd_token *token = start->data;
- struct cmd_token *copy = copy_cmd_token (token);
+ struct cmd_token *copy = cmd_token_dup (token);
copy->arg = XSTRDUP (MTYPE_CMD_ARG, input_token);
listnode_add_before (currbest, currbest->head, copy);
matcher_rv = MATCHER_OK;
@@ -677,9 +673,9 @@ match_token (struct cmd_token *token, char *input_token)
case IPV4_PREFIX_TKN:
return match_ipv4_prefix (input_token);
case IPV6_TKN:
- return match_ipv6 (input_token);
+ return match_ipv6_prefix (input_token, false);
case IPV6_PREFIX_TKN:
- return match_ipv6_prefix (input_token);
+ return match_ipv6_prefix (input_token, true);
case RANGE_TKN:
return match_range (token, input_token);
case VARIABLE_TKN:
@@ -835,35 +831,18 @@ match_ipv4_prefix (const char *str)
#define STATE_MASK 7
static enum match_type
-match_ipv6 (const char *str)
-{
- struct sockaddr_in6 sin6_dummy;
- int ret;
-
- if (strspn (str, IPV6_ADDR_STR) != strlen (str))
- return no_match;
-
- ret = inet_pton(AF_INET6, str, &sin6_dummy.sin6_addr);
-
- if (ret == 1)
- return exact_match;
-
- return no_match;
-}
-
-static enum match_type
-match_ipv6_prefix (const char *str)
+match_ipv6_prefix (const char *str, bool prefix)
{
int state = STATE_START;
int colons = 0, nums = 0, double_colon = 0;
int mask;
- const char *sp = NULL;
+ const char *sp = NULL, *start = str;
char *endptr = NULL;
if (str == NULL)
return partly_match;
- if (strspn (str, IPV6_PREFIX_STR) != strlen (str))
+ if (strspn (str, prefix ? IPV6_PREFIX_STR : IPV6_ADDR_STR) != strlen (str))
return no_match;
while (*str != '\0' && state != STATE_MASK)
@@ -966,6 +945,13 @@ match_ipv6_prefix (const char *str)
str++;
}
+ if (!prefix)
+ {
+ struct sockaddr_in6 sin6_dummy;
+ int ret = inet_pton(AF_INET6, start, &sin6_dummy.sin6_addr);
+ return ret == 1 ? exact_match : partly_match;
+ }
+
if (state < STATE_MASK)
return partly_match;
diff --git a/lib/command_match.h b/lib/command_match.h
index 9e18b8d905..a04f60f0d8 100644
--- a/lib/command_match.h
+++ b/lib/command_match.h
@@ -16,10 +16,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_COMMAND_MATCH_H
diff --git a/lib/command_parse.y b/lib/command_parse.y
index 0c415af3aa..466e3d3f1f 100644
--- a/lib/command_parse.y
+++ b/lib/command_parse.y
@@ -44,12 +44,12 @@
* struct parser_ctx is needed for the bison forward decls.
*/
%code requires {
- #include "stdlib.h"
- #include "string.h"
- #include "memory.h"
- #include "command.h"
+ #include <stdlib.h>
+ #include <string.h>
+ #include <ctype.h>
+
+ #include "command_graph.h"
#include "log.h"
- #include "graph.h"
DECLARE_MTYPE(LEX)
@@ -104,12 +104,15 @@
%type <node> start
%type <node> literal_token
%type <node> placeholder_token
+%type <node> placeholder_token_real
%type <node> simple_token
%type <subgraph> selector
%type <subgraph> selector_token
%type <subgraph> selector_token_seq
%type <subgraph> selector_seq_seq
+%type <string> varname_token
+
%code {
/* bison declarations */
@@ -184,6 +187,16 @@ start:
}
;
+varname_token: '$' WORD
+{
+ $$ = XSTRDUP (MTYPE_LEX, $2);
+}
+| /* empty */
+{
+ $$ = NULL;
+}
+;
+
cmd_token_seq:
/* empty */
| cmd_token_seq cmd_token
@@ -207,14 +220,16 @@ simple_token:
| placeholder_token
;
-literal_token: WORD
+literal_token: WORD varname_token
{
$$ = new_token_node (ctx, WORD_TKN, $1, doc_next(ctx));
+ cmd_token_varname_set ($$->data, $2);
+ XFREE (MTYPE_LEX, $2);
XFREE (MTYPE_LEX, $1);
}
;
-placeholder_token:
+placeholder_token_real:
IPV4
{
$$ = new_token_node (ctx, IPV4_TKN, $1, doc_next(ctx));
@@ -257,10 +272,22 @@ placeholder_token:
XFREE (MTYPE_LEX, $1);
}
+placeholder_token:
+ placeholder_token_real varname_token
+{
+ struct cmd_token *token = $$->data;
+ $$ = $1;
+ cmd_token_varname_set (token, $2);
+ XFREE (MTYPE_LEX, $2);
+};
+
+
/* <selector|set> productions */
-selector: '<' selector_seq_seq '>'
+selector: '<' selector_seq_seq '>' varname_token
{
$$ = $2;
+ cmd_token_varname_set ($2.end->data, $4);
+ XFREE (MTYPE_LEX, $4);
};
selector_seq_seq:
@@ -283,7 +310,7 @@ selector_seq_seq:
;
/* {keyword} productions */
-selector: '{' selector_seq_seq '}'
+selector: '{' selector_seq_seq '}' varname_token
{
$$ = $2;
graph_add_edge ($$.end, $$.start);
@@ -293,6 +320,9 @@ selector: '{' selector_seq_seq '}'
* loop-avoidal fails to handle
* just use [{a|b}] if neccessary, that will work perfectly fine, and reason
* #1 is good enough to keep it this way. */
+
+ cmd_token_varname_set ($2.end->data, $4);
+ XFREE (MTYPE_LEX, $4);
};
@@ -315,10 +345,12 @@ selector_token_seq:
;
/* [option] productions */
-selector: '[' selector_seq_seq ']'
+selector: '[' selector_seq_seq ']' varname_token
{
$$ = $2;
graph_add_edge ($$.start, $$.end);
+ cmd_token_varname_set ($2.end->data, $4);
+ XFREE (MTYPE_LEX, $4);
}
;
@@ -329,7 +361,7 @@ selector: '[' selector_seq_seq ']'
DEFINE_MTYPE(LIB, LEX, "Lexer token (temporary)")
void
-command_parse_format (struct graph *graph, struct cmd_element *cmd)
+cmd_graph_parse (struct graph *graph, struct cmd_element *cmd)
{
struct parser_ctx ctx = { .graph = graph, .el = cmd };
@@ -430,6 +462,6 @@ static struct graph_node *
new_token_node (struct parser_ctx *ctx, enum cmd_token_type type,
const char *text, const char *doc)
{
- struct cmd_token *token = new_cmd_token (type, ctx->el->attr, text, doc);
- return graph_new_node (ctx->graph, token, (void (*)(void *)) &del_cmd_token);
+ struct cmd_token *token = cmd_token_new (type, ctx->el->attr, text, doc);
+ return graph_new_node (ctx->graph, token, (void (*)(void *)) &cmd_token_del);
}
diff --git a/lib/csv.c b/lib/csv.c
index d614ac3066..bfe712bade 100644
--- a/lib/csv.c
+++ b/lib/csv.c
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Quagga; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <stdlib.h>
diff --git a/lib/csv.h b/lib/csv.h
index 3fb4453761..3ee568578c 100644
--- a/lib/csv.h
+++ b/lib/csv.h
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Quagga; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __CSV_H__
diff --git a/lib/distribute.c b/lib/distribute.c
index f85994c9a8..7b7d49d1d6 100644
--- a/lib/distribute.c
+++ b/lib/distribute.c
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
diff --git a/lib/distribute.h b/lib/distribute.h
index e9625a3548..23d7cac577 100644
--- a/lib/distribute.h
+++ b/lib/distribute.h
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_DISTRIBUTE_H
diff --git a/lib/event_counter.c b/lib/event_counter.c
index e94aa4c0f6..0acd0a1f7a 100644
--- a/lib/event_counter.c
+++ b/lib/event_counter.c
@@ -35,10 +35,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Quagga; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
diff --git a/lib/event_counter.h b/lib/event_counter.h
index f40c6cde63..8c11e10287 100644
--- a/lib/event_counter.h
+++ b/lib/event_counter.h
@@ -35,10 +35,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Quagga; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_EVENT_COUNTER_H
diff --git a/lib/fifo.h b/lib/fifo.h
index 6be75b7611..631556e78e 100644
--- a/lib/fifo.h
+++ b/lib/fifo.h
@@ -1,22 +1,22 @@
/* FIFO common header.
- Copyright (C) 2015 Kunihiro Ishiguro
-
-This file is part of Quagga.
-
-Quagga is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-Quagga is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Zebra; see the file COPYING. If not, write to the Free
-Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+ * Copyright (C) 2015 Kunihiro Ishiguro
+ *
+ * This file is part of Quagga.
+ *
+ * Quagga is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * Quagga is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
#ifndef __LIB_FIFO_H__
#define __LIB_FIFO_H__
diff --git a/lib/filter.c b/lib/filter.c
index fd73d4de73..93aac31b4f 100644
--- a/lib/filter.c
+++ b/lib/filter.c
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
diff --git a/lib/filter.h b/lib/filter.h
index 6b5ccb52ec..2c70018112 100644
--- a/lib/filter.h
+++ b/lib/filter.h
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_FILTER_H
diff --git a/lib/frr_pthread.c b/lib/frr_pthread.c
new file mode 100644
index 0000000000..17bc82f5da
--- /dev/null
+++ b/lib/frr_pthread.c
@@ -0,0 +1,183 @@
+/*
+ * Utilities and interfaces for managing POSIX threads
+ * Copyright (C) 2017 Cumulus Networks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <zebra.h>
+#include <pthread.h>
+
+#include "frr_pthread.h"
+#include "memory.h"
+#include "hash.h"
+
+DEFINE_MTYPE_STATIC(LIB, FRR_PTHREAD, "FRR POSIX Thread");
+
+static unsigned int next_id = 0;
+
+/* Hash table of all frr_pthreads along with synchronization primitive(s) and
+ * hash table callbacks.
+ * ------------------------------------------------------------------------ */
+static struct hash *pthread_table;
+static pthread_mutex_t pthread_table_mtx = PTHREAD_MUTEX_INITIALIZER;
+
+/* pthread_table->hash_cmp */
+static int pthread_table_hash_cmp(const void *value1, const void *value2)
+{
+ const struct frr_pthread *tq1 = value1;
+ const struct frr_pthread *tq2 = value2;
+
+ return (tq1->id == tq2->id);
+}
+
+/* pthread_table->hash_key */
+static unsigned int pthread_table_hash_key(void *value)
+{
+ return ((struct frr_pthread *)value)->id;
+}
+/* ------------------------------------------------------------------------ */
+
+void frr_pthread_init()
+{
+ pthread_mutex_lock(&pthread_table_mtx);
+ {
+ pthread_table =
+ hash_create(pthread_table_hash_key, pthread_table_hash_cmp);
+ }
+ pthread_mutex_unlock(&pthread_table_mtx);
+}
+
+void frr_pthread_finish()
+{
+ pthread_mutex_lock(&pthread_table_mtx);
+ {
+ hash_clean(pthread_table, (void (*)(void *))frr_pthread_destroy);
+ hash_free(pthread_table);
+ }
+ pthread_mutex_unlock(&pthread_table_mtx);
+}
+
+struct frr_pthread *frr_pthread_new(const char *name, unsigned int id,
+ void *(*start_routine) (void *),
+ int (*stop_routine) (void **, struct frr_pthread *))
+{
+ static struct frr_pthread holder = { 0 };
+ struct frr_pthread *fpt = NULL;
+
+ pthread_mutex_lock(&pthread_table_mtx);
+ {
+ holder.id = id;
+
+ if (!hash_lookup(pthread_table, &holder)) {
+ struct frr_pthread *fpt =
+ XCALLOC(MTYPE_FRR_PTHREAD,
+ sizeof(struct frr_pthread));
+ fpt->id = id;
+ fpt->master = thread_master_create();
+ fpt->start_routine = start_routine;
+ fpt->stop_routine = stop_routine;
+ fpt->name = XSTRDUP(MTYPE_FRR_PTHREAD, name);
+
+ hash_get(pthread_table, fpt, hash_alloc_intern);
+ }
+ }
+ pthread_mutex_unlock(&pthread_table_mtx);
+
+ return fpt;
+}
+
+void frr_pthread_destroy(struct frr_pthread *fpt)
+{
+ thread_master_free(fpt->master);
+ XFREE(MTYPE_FRR_PTHREAD, fpt->name);
+ XFREE(MTYPE_FRR_PTHREAD, fpt);
+}
+
+struct frr_pthread *frr_pthread_get(unsigned int id)
+{
+ static struct frr_pthread holder = { 0 };
+ struct frr_pthread *fpt;
+
+ pthread_mutex_lock(&pthread_table_mtx);
+ {
+ holder.id = id;
+ fpt = hash_lookup(pthread_table, &holder);
+ }
+ pthread_mutex_unlock(&pthread_table_mtx);
+
+ return fpt;
+}
+
+int frr_pthread_run(unsigned int id, const pthread_attr_t * attr, void *arg)
+{
+ struct frr_pthread *fpt = frr_pthread_get(id);
+ int ret;
+
+ if (!fpt)
+ return -1;
+
+ ret = pthread_create(&fpt->thread, attr, fpt->start_routine, arg);
+
+ /* Per pthread_create(3), the contents of fpt->thread are undefined if
+ * pthread_create() did not succeed. Reset this value to zero. */
+ if (ret < 0)
+ memset(&fpt->thread, 0x00, sizeof(fpt->thread));
+
+ return ret;
+}
+
+/**
+ * Calls the stop routine for the frr_pthread and resets any relevant fields.
+ *
+ * @param fpt - the frr_pthread to stop
+ * @param result - pointer to result pointer
+ * @return the return code from the stop routine
+ */
+static int frr_pthread_stop_actual(struct frr_pthread *fpt, void **result)
+{
+ int ret = (*fpt->stop_routine) (result, fpt);
+ memset(&fpt->thread, 0x00, sizeof(fpt->thread));
+ return ret;
+}
+
+int frr_pthread_stop(unsigned int id, void **result)
+{
+ struct frr_pthread *fpt = frr_pthread_get(id);
+ return frr_pthread_stop_actual(fpt, result);
+}
+
+/**
+ * Callback for hash_iterate to stop all frr_pthread's.
+ */
+static void frr_pthread_stop_all_iter(struct hash_backet *hb, void *arg)
+{
+ struct frr_pthread *fpt = hb->data;
+ frr_pthread_stop_actual(fpt, NULL);
+}
+
+void frr_pthread_stop_all()
+{
+ pthread_mutex_lock(&pthread_table_mtx);
+ {
+ hash_iterate(pthread_table, frr_pthread_stop_all_iter, NULL);
+ }
+ pthread_mutex_unlock(&pthread_table_mtx);
+}
+
+unsigned int frr_pthread_get_id()
+{
+ return next_id++;
+}
diff --git a/lib/frr_pthread.h b/lib/frr_pthread.h
new file mode 100644
index 0000000000..1a390b1e45
--- /dev/null
+++ b/lib/frr_pthread.h
@@ -0,0 +1,144 @@
+/*
+ * Utilities and interfaces for managing POSIX threads
+ * Copyright (C) 2017 Cumulus Networks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef _FRR_PTHREAD_H
+#define _FRR_PTHREAD_H
+
+#include <pthread.h>
+#include "thread.h"
+
+struct frr_pthread {
+
+ /* pthread id */
+ pthread_t thread;
+
+ /* frr thread identifier */
+ unsigned int id;
+
+ /* thread master for this pthread's thread.c event loop */
+ struct thread_master *master;
+
+ /* start routine */
+ void *(*start_routine) (void *);
+
+ /* stop routine */
+ int (*stop_routine) (void **, struct frr_pthread *);
+
+ /* the (hopefully descriptive) name of this thread */
+ char *name;
+};
+
+/* Initializes this module.
+ *
+ * Must be called before using any of the other functions.
+ */
+void frr_pthread_init(void);
+
+/* Uninitializes this module.
+ *
+ * Destroys all registered frr_pthread's and internal data structures.
+ *
+ * It is safe to call frr_pthread_init() after this function to reinitialize
+ * the module.
+ */
+void frr_pthread_finish(void);
+
+/* Creates a new frr_pthread.
+ *
+ * If the provided ID is already assigned to an existing frr_pthread, the
+ * return value will be NULL.
+ *
+ * @param name - the name of the thread. Doesn't have to be unique, but it
+ * probably should be. This value is copied and may be safely free'd upon
+ * return.
+ *
+ * @param id - the integral ID of the thread. MUST be unique. The caller may
+ * use this id to retrieve the thread.
+ *
+ * @param start_routine - start routine for the pthread, will be passed to
+ * pthread_create (see those docs for details)
+ *
+ * @param stop_routine - stop routine for the pthread, called to terminate the
+ * thread. This function should gracefully stop the pthread and clean up any
+ * thread-specific resources. The passed pointer is used to return a data
+ * result.
+ *
+ * @return the created frr_pthread upon success, or NULL upon failure
+ */
+struct frr_pthread *frr_pthread_new(const char *name, unsigned int id,
+ void *(*start_routine) (void *),
+ int (*stop_routine) (void **, struct frr_pthread *));
+
+/* Destroys an frr_pthread.
+ *
+ * Assumes that the associated pthread, if any, has already terminated.
+ *
+ * @param fpt - the frr_pthread to destroy
+ */
+void frr_pthread_destroy(struct frr_pthread *fpt);
+
+/* Gets an existing frr_pthread by its id.
+ *
+ * @return frr_thread associated with the provided id, or NULL on error
+ */
+struct frr_pthread *frr_pthread_get(unsigned int id);
+
+/* Creates a new pthread and binds it to a frr_pthread.
+ *
+ * This function is a wrapper for pthread_create. The first parameter is the
+ * frr_pthread to bind the created pthread to. All subsequent arguments are
+ * passed unmodified to pthread_create().
+ *
+ * This function returns the same code as pthread_create(). If the value is
+ * zero, the provided frr_pthread is bound to a running POSIX thread. If the
+ * value is less than zero, the provided frr_pthread is guaranteed to be a
+ * clean instance that may be susbsequently passed to frr_pthread_run().
+ *
+ * @param id - frr_pthread to bind the created pthread to
+ * @param attr - see pthread_create(3)
+ * @param arg - see pthread_create(3)
+ *
+ * @return see pthread_create(3)
+ */
+int frr_pthread_run(unsigned int id, const pthread_attr_t * attr, void *arg);
+
+/* Stops an frr_pthread with a result.
+ *
+ * @param id - frr_pthread to stop
+ * @param result - where to store the thread's result, if any. May be NULL if a
+ * result is not needed.
+ */
+int frr_pthread_stop(unsigned int id, void **result);
+
+/* Stops all frr_pthread's. */
+void frr_pthread_stop_all(void);
+
+/* Returns a unique identifier for use with frr_pthread_new().
+ *
+ * Internally, this is an integer that increments after each call to this
+ * function. Because the number of pthreads created should never exceed INT_MAX
+ * during the life of the program, there is no overflow protection. If by
+ * chance this function returns an ID which is already in use,
+ * frr_pthread_new() will fail when it is provided.
+ *
+ * @return unique identifier
+ */
+unsigned int frr_pthread_get_id(void);
+
+#endif /* _FRR_PTHREAD_H */
diff --git a/lib/frratomic.h b/lib/frratomic.h
new file mode 100644
index 0000000000..183790aeb0
--- /dev/null
+++ b/lib/frratomic.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2015-16 David Lamparter, for NetDEF, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _FRRATOMIC_H
+#define _FRRATOMIC_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifndef FRR_AUTOCONF_ATOMIC
+#error autoconf checks for atomic functions were not properly run
+#endif
+
+/* ISO C11 */
+#ifdef HAVE_STDATOMIC_H
+#include <stdatomic.h>
+
+/* gcc 4.7 and newer */
+#elif defined(HAVE___ATOMIC)
+
+#define _Atomic volatile
+
+#define memory_order_relaxed __ATOMIC_RELAXED
+#define memory_order_consume __ATOMIC_CONSUME
+#define memory_order_acquire __ATOMIC_ACQUIRE
+#define memory_order_release __ATOMIC_RELEASE
+#define memory_order_acq_rel __ATOMIC_ACQ_REL
+#define memory_order_seq_cst __ATOMIC_SEQ_CST
+
+#define atomic_load_explicit __atomic_load_n
+#define atomic_store_explicit __atomic_store_n
+#define atomic_exchange_explicit __atomic_exchange_n
+#define atomic_fetch_add_explicit __atomic_fetch_add
+#define atomic_fetch_sub_explicit __atomic_fetch_sub
+
+#define atomic_compare_exchange_weak_explicit(atom, expect, desire, mem1, mem2) \
+ __atomic_compare_exchange_n(atom, expect, desire, 1, mem1, mem2)
+
+/* gcc 4.1 and newer,
+ * clang 3.3 (possibly older)
+ *
+ * __sync_swap isn't in gcc's documentation, but clang has it
+ *
+ * note __sync_synchronize()
+ */
+#elif defined(HAVE___SYNC)
+
+#define _Atomic volatile
+
+#define memory_order_relaxed 0
+#define memory_order_consume 0
+#define memory_order_acquire 0
+#define memory_order_release 0
+#define memory_order_acq_rel 0
+#define memory_order_seq_cst 0
+
+#define atomic_load_explicit(ptr, mem) \
+ ({ __sync_synchronize(); \
+ typeof(*ptr) rval = __sync_fetch_and_add((ptr), 0); \
+ __sync_synchronize(); rval; })
+#define atomic_store_explicit(ptr, val, mem) \
+ ({ __sync_synchronize(); \
+ *(ptr) = (val); \
+ __sync_synchronize(); (void)0; })
+#ifdef HAVE___SYNC_SWAP
+#define atomic_exchange_explicit(ptr, val, mem) \
+ ({ __sync_synchronize(); \
+ typeof(*ptr) rval = __sync_swap((ptr, val), 0); \
+ __sync_synchronize(); rval; })
+#else /* !HAVE___SYNC_SWAP */
+#define atomic_exchange_explicit(ptr, val, mem) \
+ ({ typeof(ptr) _ptr = (ptr); typeof(val) _val = (val); \
+ __sync_synchronize(); \
+ typeof(*ptr) old1, old2 = __sync_fetch_and_add(_ptr, 0); \
+ do { \
+ old1 = old2; \
+ old2 = __sync_val_compare_and_swap (_ptr, old1, _val); \
+ } while (old1 != old2); \
+ __sync_synchronize(); \
+ old2; \
+ })
+#endif /* !HAVE___SYNC_SWAP */
+#define atomic_fetch_add_explicit(ptr, val, mem) \
+ ({ __sync_synchronize(); \
+ typeof(*ptr) rval = __sync_fetch_and_add((ptr), (val)); \
+ __sync_synchronize(); rval; })
+#define atomic_fetch_sub_explicit(ptr, val, mem) \
+ ({ __sync_synchronize(); \
+ typeof(*ptr) rval = __sync_fetch_and_sub((ptr), (val)); \
+ __sync_synchronize(); rval; })
+
+#define atomic_compare_exchange_weak_explicit(atom, expect, desire, mem1, mem2) \
+ ({ typeof(atom) _atom = (atom); typeof(expect) _expect = (expect); \
+ typeof(desire) _desire = (desire); \
+ __sync_synchronize(); \
+ typeof(*atom) rval = __sync_val_compare_and_swap(_atom, *_expect, _desire); \
+ __sync_synchronize(); \
+ bool ret = (rval == *_expect); *_expect = rval; ret; })
+
+#else /* !HAVE___ATOMIC && !HAVE_STDATOMIC_H */
+#error no atomic functions...
+#endif
+
+#endif /* _FRRATOMIC_H */
diff --git a/lib/getopt.c b/lib/getopt.c
index 7a58a8a8cc..d0ee43510b 100644
--- a/lib/getopt.c
+++ b/lib/getopt.c
@@ -1,28 +1,28 @@
/* Getopt for GNU.
- NOTE: getopt is now part of the C library, so if you don't know what
- "Keep this file name-space clean" means, talk to drepper@gnu.org
- before changing it!
-
- Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98
- Free Software Foundation, Inc.
-
- NOTE: The canonical source of this file is maintained with the GNU C Library.
- Bugs can be reported to bug-glibc@gnu.org.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- USA. */
+ * NOTE: getopt is now part of the C library, so if you don't know what
+ * "Keep this file name-space clean" means, talk to drepper@gnu.org
+ * before changing it!
+ *
+ * Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98
+ * Free Software Foundation, Inc.
+ *
+ * NOTE: The canonical source of this file is maintained with the GNU C Library.
+ * Bugs can be reported to bug-glibc@gnu.org.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
Ditto for AIX 3.2 and <stdlib.h>. */
diff --git a/lib/getopt.h b/lib/getopt.h
index b359a47beb..cc38a45c23 100644
--- a/lib/getopt.h
+++ b/lib/getopt.h
@@ -1,23 +1,23 @@
/* Declarations for getopt.
- Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc.
-
- NOTE: The canonical source of this file is maintained with the GNU C Library.
- Bugs can be reported to bug-glibc@gnu.org.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- USA. */
+ * Copyright (C) 1989,90,91,92,93,94,96,97 Free Software Foundation, Inc.
+ *
+ * NOTE: The canonical source of this file is maintained with the GNU C Library.
+ * Bugs can be reported to bug-glibc@gnu.org.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
#ifndef _GETOPT_H
#define _GETOPT_H 1
diff --git a/lib/getopt1.c b/lib/getopt1.c
index bd3099e799..1873a197e1 100644
--- a/lib/getopt1.c
+++ b/lib/getopt1.c
@@ -1,24 +1,24 @@
/* getopt_long and getopt_long_only entry points for GNU getopt.
- Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
- Free Software Foundation, Inc.
-
- NOTE: The canonical source of this file is maintained with the GNU C Library.
- Bugs can be reported to bug-glibc@gnu.org.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- USA. */
+ * Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
+ * Free Software Foundation, Inc.
+ *
+ * NOTE: The canonical source of this file is maintained with the GNU C Library.
+ * Bugs can be reported to bug-glibc@gnu.org.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
#include <zebra.h>
#include "getopt.h"
diff --git a/lib/grammar_sandbox.c b/lib/grammar_sandbox.c
index 0da7981fc1..cfc3fb7982 100644
--- a/lib/grammar_sandbox.c
+++ b/lib/grammar_sandbox.c
@@ -18,10 +18,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "command.h"
@@ -70,11 +69,11 @@ DEFUN (grammar_test,
// parse the command and install it into the command graph
struct graph *graph = graph_new();
- struct cmd_token *token = new_cmd_token (START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
- graph_new_node (graph, token, (void (*)(void *)) &del_cmd_token);
+ struct cmd_token *token = cmd_token_new (START_TKN, CMD_ATTR_NORMAL, NULL, NULL);
+ graph_new_node (graph, token, (void (*)(void *)) &cmd_token_del);
- command_parse_format (graph, cmd);
- cmd_merge_graphs (nodegraph, graph, +1);
+ cmd_graph_parse (graph, cmd);
+ cmd_graph_merge (nodegraph, graph, +1);
return CMD_SUCCESS;
}
@@ -123,7 +122,7 @@ DEFUN (grammar_test_complete,
}
for (i = 0; i < vector_active (comps); i++)
- del_cmd_token ((struct cmd_token *) vector_slot (comps, i));
+ cmd_token_del ((struct cmd_token *) vector_slot (comps, i));
vector_free (comps);
}
else
@@ -229,7 +228,7 @@ DEFUN (grammar_test_doc,
cmd->func = NULL;
// parse element
- command_parse_format (nodegraph, cmd);
+ cmd_graph_parse (nodegraph, cmd);
return CMD_SUCCESS;
}
@@ -526,6 +525,8 @@ pretty_print_graph (struct vty *vty, struct graph_node *start, int level,
vty_out(vty, "%s", LOOKUP_DEF(tokennames, tok->type, tokennum));
if (tok->text)
vty_out(vty, ":\"%s\"", tok->text);
+ if (tok->varname)
+ vty_out(vty, " => %s", tok->varname);
if (desc)
vty_out(vty, " ?'%s'", tok->desc);
vty_out(vty, " ");
@@ -647,8 +648,8 @@ init_cmdgraph (struct vty *vty, struct graph **graph)
// initialize graph, add start noe
*graph = graph_new ();
nodegraph_free = *graph;
- struct cmd_token *token = new_cmd_token (START_TKN, 0, NULL, NULL);
- graph_new_node (*graph, token, (void (*)(void *)) &del_cmd_token);
+ struct cmd_token *token = cmd_token_new (START_TKN, 0, NULL, NULL);
+ graph_new_node (*graph, token, (void (*)(void *)) &cmd_token_del);
if (vty)
vty_out (vty, "initialized graph%s", VTY_NEWLINE);
}
diff --git a/lib/grammar_sandbox_main.c b/lib/grammar_sandbox_main.c
index 681d4da440..3bf0e268cf 100644
--- a/lib/grammar_sandbox_main.c
+++ b/lib/grammar_sandbox_main.c
@@ -19,8 +19,8 @@
* details.
*
* You should have received a copy of the GNU General Public License along
- * with FRR; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "command.h"
diff --git a/lib/graph.c b/lib/graph.c
index 0992059ef1..6173b2084b 100644
--- a/lib/graph.c
+++ b/lib/graph.c
@@ -16,10 +16,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
#include "graph.h"
diff --git a/lib/graph.h b/lib/graph.h
index 8d8aa3823b..d3973d4b02 100644
--- a/lib/graph.h
+++ b/lib/graph.h
@@ -16,10 +16,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_COMMAND_GRAPH_H
diff --git a/lib/hash.c b/lib/hash.c
index cb8531fccf..553a137eb6 100644
--- a/lib/hash.c
+++ b/lib/hash.c
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
diff --git a/lib/hash.h b/lib/hash.h
index 11ecf75ec9..bafb35a2a3 100644
--- a/lib/hash.h
+++ b/lib/hash.h
@@ -1,22 +1,22 @@
/* Hash routine.
- Copyright (C) 1998 Kunihiro Ishiguro
-
-This file is part of GNU Zebra.
-
-GNU Zebra is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published
-by the Free Software Foundation; either version 2, or (at your
-option) any later version.
-
-GNU Zebra is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Zebra; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+ * Copyright (C) 1998 Kunihiro Ishiguro
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
#ifndef _ZEBRA_HASH_H
#define _ZEBRA_HASH_H
diff --git a/lib/if.c b/lib/if.c
index ecb7463168..dc417f8e3c 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -1,10 +1,9 @@
-
/*
* Interface functions.
* Copyright (C) 1997, 98 Kunihiro Ishiguro
*
* This file is part of GNU Zebra.
- *
+ *
* GNU Zebra is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2, or (at your
@@ -15,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
@@ -1126,6 +1124,36 @@ ifaddr_ipv4_lookup (struct in_addr *addr, ifindex_t ifindex)
}
#endif /* ifaddr_ipv4_table */
+static void if_autocomplete(vector comps, struct cmd_token *token)
+{
+ struct interface *ifp;
+ struct listnode *ln;
+ struct vrf *vrf = NULL;
+
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
+ {
+ for (ALL_LIST_ELEMENTS_RO(vrf->iflist, ln, ifp))
+ vector_set (comps, XSTRDUP (MTYPE_COMPLETION, ifp->name));
+ }
+
+}
+
+static const struct cmd_variable_handler if_var_handlers[] = {
+ {
+ /* "interface NAME" */
+ .varname = "interface",
+ .completions = if_autocomplete
+ }, {
+ .tokenname = "IFNAME",
+ .completions = if_autocomplete
+ }, {
+ .tokenname = "INTERFACE",
+ .completions = if_autocomplete
+ }, {
+ .completions = NULL
+ }
+};
+
/* Initialize interface list. */
void
if_init (struct list **intf_list)
@@ -1136,6 +1164,8 @@ if_init (struct list **intf_list)
#endif /* ifaddr_ipv4_table */
(*intf_list)->cmp = (int (*)(void *, void *))if_cmp_func;
+
+ cmd_variable_handler_register(if_var_handlers);
}
void
diff --git a/lib/if.h b/lib/if.h
index e8e84ffc88..fa95901a58 100644
--- a/lib/if.h
+++ b/lib/if.h
@@ -1,22 +1,22 @@
/* Interface related header.
- Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
-
-This file is part of GNU Zebra.
-
-GNU Zebra is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published
-by the Free Software Foundation; either version 2, or (at your
-option) any later version.
-
-GNU Zebra is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Zebra; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+ * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
#ifndef _ZEBRA_IF_H
#define _ZEBRA_IF_H
diff --git a/lib/if_rmap.c b/lib/if_rmap.c
index 2afb08c7ca..fa9b17f2ae 100644
--- a/lib/if_rmap.c
+++ b/lib/if_rmap.c
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
diff --git a/lib/if_rmap.h b/lib/if_rmap.h
index e6c2966ff8..e38b5f7f73 100644
--- a/lib/if_rmap.h
+++ b/lib/if_rmap.h
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_IF_RMAP_H
diff --git a/lib/json.c b/lib/json.c
index ccbecb726a..186efc9f48 100644
--- a/lib/json.c
+++ b/lib/json.c
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
diff --git a/lib/json.h b/lib/json.h
index 7e98614280..5faaaa841a 100644
--- a/lib/json.h
+++ b/lib/json.h
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _QUAGGA_JSON_H
diff --git a/lib/keychain.c b/lib/keychain.c
index 95a2c8e599..1aa6edb4bd 100644
--- a/lib/keychain.c
+++ b/lib/keychain.c
@@ -1,22 +1,22 @@
/* key-chain for authentication.
- Copyright (C) 2000 Kunihiro Ishiguro
-
-This file is part of GNU Zebra.
-
-GNU Zebra is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published
-by the Free Software Foundation; either version 2, or (at your
-option) any later version.
-
-GNU Zebra is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Zebra; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+ * Copyright (C) 2000 Kunihiro Ishiguro
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
#include <zebra.h>
diff --git a/lib/keychain.h b/lib/keychain.h
index d3f9168a0f..e6bdcc6f06 100644
--- a/lib/keychain.h
+++ b/lib/keychain.h
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_KEYCHAIN_H
diff --git a/lib/libfrr.c b/lib/libfrr.c
index de83e14f0e..16681fe578 100644
--- a/lib/libfrr.c
+++ b/lib/libfrr.c
@@ -13,9 +13,9 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
diff --git a/lib/libfrr.h b/lib/libfrr.h
index 0cc7ad564b..6bd92d8bea 100644
--- a/lib/libfrr.h
+++ b/lib/libfrr.h
@@ -13,9 +13,9 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_FRR_H
diff --git a/lib/libospf.h b/lib/libospf.h
index a1ff9c24a2..c9483a4c65 100644
--- a/lib/libospf.h
+++ b/lib/libospf.h
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _LIBOSPFD_H
diff --git a/lib/linklist.c b/lib/linklist.c
index 6fe91c75fc..0aee54d44c 100644
--- a/lib/linklist.c
+++ b/lib/linklist.c
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
diff --git a/lib/linklist.h b/lib/linklist.h
index cd6e2f13aa..37ba396a76 100644
--- a/lib/linklist.h
+++ b/lib/linklist.h
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_LINKLIST_H
diff --git a/lib/log.c b/lib/log.c
index c7d4ca2d97..111b98758d 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define FRR_DEFINE_DESC_TABLE
@@ -734,6 +733,17 @@ openzlog (const char *progname, const char *protoname, u_short instance,
openlog (progname, syslog_flags, zl->facility);
zlog_default = zl;
+
+#ifdef HAVE_GLIBC_BACKTRACE
+ /* work around backtrace() using lazily resolved dynamically linked
+ * symbols, which will otherwise cause funny breakage in the SEGV handler.
+ * (particularly, the dynamic linker can call malloc(), which uses locks
+ * in programs linked with -pthread, thus can deadlock.) */
+ void *bt[4];
+ backtrace (bt, array_size(bt));
+ free (backtrace_symbols (bt, 0));
+ backtrace_symbols_fd (bt, 0, 0);
+#endif
}
void
@@ -1047,6 +1057,8 @@ proto_redistnum(int afi, const char *s)
return ZEBRA_ROUTE_STATIC;
else if (strmatch (s, "rip"))
return ZEBRA_ROUTE_RIP;
+ else if (strmatch (s, "eigrp"))
+ return ZEBRA_ROUTE_EIGRP;
else if (strmatch (s, "ospf"))
return ZEBRA_ROUTE_OSPF;
else if (strmatch (s, "isis"))
diff --git a/lib/log.h b/lib/log.h
index cc419cc374..f6c94ba604 100644
--- a/lib/log.h
+++ b/lib/log.h
@@ -14,16 +14,16 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_LOG_H
#define _ZEBRA_LOG_H
#include <syslog.h>
+#include <stdint.h>
#include <stdio.h>
/* Here is some guidance on logging levels to use:
@@ -64,7 +64,7 @@ struct message
/* Open zlog function */
extern void openzlog (const char *progname, const char *protoname,
- u_short instance, int syslog_options, int syslog_facility);
+ uint16_t instance, int syslog_options, int syslog_facility);
/* Close zlog function. */
extern void closezlog (void);
diff --git a/lib/log_int.h b/lib/log_int.h
index c21d723ac6..7c93381cbc 100644
--- a/lib/log_int.h
+++ b/lib/log_int.h
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_LOG_PRIVATE_H
diff --git a/lib/memory.c b/lib/memory.c
index ad55366f64..c6207adb98 100644
--- a/lib/memory.c
+++ b/lib/memory.c
@@ -27,119 +27,107 @@ struct memgroup **mg_insert = &mg_first;
DEFINE_MGROUP(LIB, "libfrr")
DEFINE_MTYPE(LIB, TMP, "Temporary memory")
-static inline void
-mt_count_alloc (struct memtype *mt, size_t size)
+static inline void mt_count_alloc(struct memtype *mt, size_t size)
{
- mt->n_alloc++;
+ size_t oldsize;
- if (mt->size == 0)
- mt->size = size;
- else if (mt->size != size)
- mt->size = SIZE_VAR;
+ atomic_fetch_add_explicit(&mt->n_alloc, 1, memory_order_relaxed);
+
+ oldsize = atomic_load_explicit(&mt->size, memory_order_relaxed);
+ if (oldsize == 0)
+ oldsize = atomic_exchange_explicit(&mt->size, size, memory_order_relaxed);
+ if (oldsize != 0 && oldsize != size && oldsize != SIZE_VAR)
+ atomic_store_explicit(&mt->size, SIZE_VAR, memory_order_relaxed);
}
-static inline void
-mt_count_free (struct memtype *mt)
+static inline void mt_count_free(struct memtype *mt)
{
- assert(mt->n_alloc);
- mt->n_alloc--;
+ assert(mt->n_alloc);
+ atomic_fetch_sub_explicit(&mt->n_alloc, 1, memory_order_relaxed);
}
-static inline void *
-mt_checkalloc (struct memtype *mt, void *ptr, size_t size)
+static inline void *mt_checkalloc(struct memtype *mt, void *ptr, size_t size)
{
- if (__builtin_expect(ptr == NULL, 0))
- {
- memory_oom (size, mt->name);
- return NULL;
- }
- mt_count_alloc (mt, size);
- return ptr;
+ if (__builtin_expect(ptr == NULL, 0)) {
+ memory_oom(size, mt->name);
+ return NULL;
+ }
+ mt_count_alloc(mt, size);
+ return ptr;
}
-void *
-qmalloc (struct memtype *mt, size_t size)
+void *qmalloc(struct memtype *mt, size_t size)
{
- return mt_checkalloc (mt, malloc (size), size);
+ return mt_checkalloc(mt, malloc(size), size);
}
-void *
-qcalloc (struct memtype *mt, size_t size)
+void *qcalloc(struct memtype *mt, size_t size)
{
- return mt_checkalloc (mt, calloc (size, 1), size);
+ return mt_checkalloc(mt, calloc(size, 1), size);
}
-void *
-qrealloc (struct memtype *mt, void *ptr, size_t size)
+void *qrealloc(struct memtype *mt, void *ptr, size_t size)
{
- if (ptr)
- mt_count_free (mt);
- return mt_checkalloc (mt, ptr ? realloc (ptr, size) : malloc (size), size);
+ if (ptr)
+ mt_count_free(mt);
+ return mt_checkalloc(mt, ptr ? realloc(ptr, size) : malloc(size), size);
}
-void *
-qstrdup (struct memtype *mt, const char *str)
+void *qstrdup(struct memtype *mt, const char *str)
{
- return mt_checkalloc (mt, strdup (str), strlen (str) + 1);
+ return mt_checkalloc(mt, strdup(str), strlen(str) + 1);
}
-void
-qfree (struct memtype *mt, void *ptr)
+void qfree(struct memtype *mt, void *ptr)
{
- if (ptr)
- mt_count_free (mt);
- free (ptr);
+ if (ptr)
+ mt_count_free(mt);
+ free(ptr);
}
-int
-qmem_walk (qmem_walk_fn *func, void *arg)
+int qmem_walk(qmem_walk_fn *func, void *arg)
{
- struct memgroup *mg;
- struct memtype *mt;
- int rv;
-
- for (mg = mg_first; mg; mg = mg->next)
- {
- if ((rv = func (arg, mg, NULL)))
- return rv;
- for (mt = mg->types; mt; mt = mt->next)
- if ((rv = func (arg, mg, mt)))
- return rv;
- }
- return 0;
+ struct memgroup *mg;
+ struct memtype *mt;
+ int rv;
+
+ for (mg = mg_first; mg; mg = mg->next) {
+ if ((rv = func(arg, mg, NULL)))
+ return rv;
+ for (mt = mg->types; mt; mt = mt->next)
+ if ((rv = func(arg, mg, mt)))
+ return rv;
+ }
+ return 0;
}
-struct exit_dump_args
-{
- const char *prefix;
- int error;
+struct exit_dump_args {
+ const char *prefix;
+ int error;
};
-static int
-qmem_exit_walker (void *arg, struct memgroup *mg, struct memtype *mt)
+static int qmem_exit_walker(void *arg, struct memgroup *mg, struct memtype *mt)
{
- struct exit_dump_args *eda = arg;
-
- if (!mt)
- {
- fprintf (stderr, "%s: showing active allocations in memory group %s\n",
- eda->prefix, mg->name);
- }
- else if (mt->n_alloc)
- {
- char size[32];
- eda->error++;
- snprintf (size, sizeof (size), "%10zu", mt->size);
- fprintf (stderr, "%s: memstats: %-30s: %6zu * %s\n",
- eda->prefix, mt->name, mt->n_alloc,
- mt->size == SIZE_VAR ? "(variably sized)" : size);
- }
- return 0;
+ struct exit_dump_args *eda = arg;
+
+ if (!mt) {
+ fprintf(stderr, "%s: showing active allocations in "
+ "memory group %s\n",
+ eda->prefix, mg->name);
+
+ } else if (mt->n_alloc) {
+ char size[32];
+ eda->error++;
+ snprintf(size, sizeof(size), "%10zu", mt->size);
+ fprintf(stderr, "%s: memstats: %-30s: %6zu * %s\n",
+ eda->prefix, mt->name, mt->n_alloc,
+ mt->size == SIZE_VAR ? "(variably sized)" : size);
+ }
+ return 0;
}
-void
-log_memstats_stderr (const char *prefix)
+void log_memstats_stderr(const char *prefix)
{
- struct exit_dump_args eda = { .prefix = prefix, .error = 0 };
- qmem_walk (qmem_exit_walker, &eda);
+ struct exit_dump_args eda = { .prefix = prefix, .error = 0 };
+ qmem_walk(qmem_exit_walker, &eda);
}
diff --git a/lib/memory.h b/lib/memory.h
index 477a6162dc..9e8803a8b2 100644
--- a/lib/memory.h
+++ b/lib/memory.h
@@ -18,23 +18,22 @@
#define _QUAGGA_MEMORY_H
#include <stdlib.h>
+#include <frratomic.h>
#define array_size(ar) (sizeof(ar) / sizeof(ar[0]))
#define SIZE_VAR ~0UL
-struct memtype
-{
- struct memtype *next, **ref;
- const char *name;
- size_t n_alloc;
- size_t size;
+struct memtype {
+ struct memtype *next, **ref;
+ const char *name;
+ _Atomic size_t n_alloc;
+ _Atomic size_t size;
};
-struct memgroup
-{
- struct memgroup *next, **ref;
- struct memtype *types, **insert;
- const char *name;
+struct memgroup {
+ struct memgroup *next, **ref;
+ struct memtype *types, **insert;
+ const char *name;
};
#if defined(__clang__)
@@ -82,14 +81,14 @@ struct memgroup
* DEFINE_MGROUP(MYDAEMON, "my daemon memory")
* DEFINE_MTYPE(MYDAEMON, MYDAEMON_COMMON,
* "this mtype is used in multiple files in mydaemon")
- * foo = qmalloc (MTYPE_MYDAEMON_COMMON, sizeof (*foo))
+ * foo = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*foo))
*
* mydaemon_io.c
- * bar = qmalloc (MTYPE_MYDAEMON_COMMON, sizeof (*bar))
+ * bar = qmalloc(MTYPE_MYDAEMON_COMMON, sizeof(*bar))
*
* DEFINE_MTYPE_STATIC(MYDAEMON, MYDAEMON_IO,
* "this mtype is used only in this file")
- * baz = qmalloc (MTYPE_MYDAEMON_IO, sizeof (*baz))
+ * baz = qmalloc(MTYPE_MYDAEMON_IO, sizeof(*baz))
*
* Note: Naming conventions (MGROUP_ and MTYPE_ prefixes are enforced
* by not having these as part of the macro arguments)
@@ -155,15 +154,15 @@ DECLARE_MGROUP(LIB)
DECLARE_MTYPE(TMP)
-extern void *qmalloc (struct memtype *mt, size_t size)
+extern void *qmalloc(struct memtype *mt, size_t size)
__attribute__ ((malloc, _ALLOC_SIZE(2), nonnull (1) _RET_NONNULL));
-extern void *qcalloc (struct memtype *mt, size_t size)
+extern void *qcalloc(struct memtype *mt, size_t size)
__attribute__ ((malloc, _ALLOC_SIZE(2), nonnull (1) _RET_NONNULL));
-extern void *qrealloc (struct memtype *mt, void *ptr, size_t size)
+extern void *qrealloc(struct memtype *mt, void *ptr, size_t size)
__attribute__ ((_ALLOC_SIZE(3), nonnull (1) _RET_NONNULL));
extern void *qstrdup (struct memtype *mt, const char *str)
__attribute__ ((malloc, nonnull (1) _RET_NONNULL));
-extern void qfree (struct memtype *mt, void *ptr)
+extern void qfree(struct memtype *mt, void *ptr)
__attribute__ ((nonnull (1)));
#define XMALLOC(mtype, size) qmalloc(mtype, size)
@@ -183,10 +182,10 @@ static inline size_t mtype_stats_alloc(struct memtype *mt)
*
* return value: 0: continue, !0: abort walk. qmem_walk will return the
* last value from qmem_walk_fn. */
-typedef int qmem_walk_fn (void *arg, struct memgroup *mg, struct memtype *mt);
-extern int qmem_walk (qmem_walk_fn *func, void *arg);
-extern void log_memstats_stderr (const char *);
+typedef int qmem_walk_fn(void *arg, struct memgroup *mg, struct memtype *mt);
+extern int qmem_walk(qmem_walk_fn *func, void *arg);
+extern void log_memstats_stderr(const char *);
-extern void memory_oom (size_t size, const char *name);
+extern void memory_oom(size_t size, const char *name);
#endif /* _QUAGGA_MEMORY_H */
diff --git a/lib/memory_vty.c b/lib/memory_vty.c
index 6d63bc2d53..27254cfa5b 100644
--- a/lib/memory_vty.c
+++ b/lib/memory_vty.c
@@ -14,9 +14,9 @@
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
diff --git a/lib/memory_vty.h b/lib/memory_vty.h
index 565a75aa98..a47c5d51b8 100644
--- a/lib/memory_vty.h
+++ b/lib/memory_vty.h
@@ -1,22 +1,22 @@
/* Memory management routine
- Copyright (C) 1998 Kunihiro Ishiguro
-
-This file is part of GNU Zebra.
-
-GNU Zebra is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-GNU Zebra is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Zebra; see the file COPYING. If not, write to the Free
-Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+ * Copyright (C) 1998 Kunihiro Ishiguro
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
#ifndef _ZEBRA_MEMORY_VTY_H
#define _ZEBRA_MEMORY_VTY_H
diff --git a/lib/mpls.h b/lib/mpls.h
index 13a46e1012..6cf0142755 100644
--- a/lib/mpls.h
+++ b/lib/mpls.h
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _QUAGGA_MPLS_H
@@ -85,7 +84,8 @@ enum lsp_types_t
{
ZEBRA_LSP_NONE = 0, /* No LSP. */
ZEBRA_LSP_STATIC = 1, /* Static LSP. */
- ZEBRA_LSP_LDP = 2 /* LDP LSP. */
+ ZEBRA_LSP_LDP = 2, /* LDP LSP. */
+ ZEBRA_LSP_BGP = 3 /* BGP LSP. */
};
/* Functions for basic label operations. */
@@ -122,6 +122,11 @@ mpls_lse_decode (mpls_lse_t lse, mpls_label_t *label,
*ttl = MPLS_LABEL_TTL(local_lse);
}
+/* Invalid label index value (when used with BGP Prefix-SID). Should
+ * match the BGP definition.
+ */
+#define MPLS_INVALID_LABEL_INDEX 0xFFFFFFFF
+
/* Printable string for labels (with consideration for reserved values). */
static inline char *
diff --git a/lib/network.c b/lib/network.c
index 2b6f2fbab5..3d2c63c89d 100644
--- a/lib/network.c
+++ b/lib/network.c
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
diff --git a/lib/network.h b/lib/network.h
index a9126caf7f..a6b8ed1e17 100644
--- a/lib/network.h
+++ b/lib/network.h
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_NETWORK_H
diff --git a/lib/nexthop.c b/lib/nexthop.c
index 7b8ac95e83..725b52c052 100644
--- a/lib/nexthop.c
+++ b/lib/nexthop.c
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Quagga; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
@@ -92,6 +91,28 @@ nexthop_type_to_str (enum nexthop_types_t nh_type)
return desc[nh_type];
}
+/*
+ * Check if the labels match for the 2 nexthops specified.
+ */
+int
+nexthop_labels_match (struct nexthop *nh1, struct nexthop *nh2)
+{
+ struct nexthop_label *nhl1, *nhl2;
+
+ nhl1 = nh1->nh_label;
+ nhl2 = nh2->nh_label;
+ if ((nhl1 && !nhl2) || (!nhl1 && nhl2))
+ return 0;
+
+ if (nhl1->num_labels != nhl2->num_labels)
+ return 0;
+
+ if (memcmp (nhl1->label, nhl2->label, nhl1->num_labels))
+ return 0;
+
+ return 1;
+}
+
struct nexthop *
nexthop_new (void)
{
diff --git a/lib/nexthop.h b/lib/nexthop.h
index e66e0eee20..8c9c801c91 100644
--- a/lib/nexthop.h
+++ b/lib/nexthop.h
@@ -15,10 +15,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Quagga; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _LIB_NEXTHOP_H
@@ -117,6 +116,7 @@ void nexthop_del_labels (struct nexthop *);
extern const char *nexthop_type_to_str (enum nexthop_types_t nh_type);
extern int nexthop_same_no_recurse (struct nexthop *next1, struct nexthop *next2);
+extern int nexthop_labels_match (struct nexthop *nh1, struct nexthop *nh2);
extern const char * nexthop2str (struct nexthop *nexthop, char *str, int size);
#endif /*_LIB_NEXTHOP_H */
diff --git a/lib/ns.c b/lib/ns.c
index ae0a24668e..8c489d68fd 100644
--- a/lib/ns.c
+++ b/lib/ns.c
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
diff --git a/lib/ns.h b/lib/ns.h
index 2a7be1ef8a..98fd3fa18c 100644
--- a/lib/ns.h
+++ b/lib/ns.h
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_NS_H
diff --git a/lib/pid_output.c b/lib/pid_output.c
index ba1f37476e..7369e23c20 100644
--- a/lib/pid_output.c
+++ b/lib/pid_output.c
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
diff --git a/lib/plist.c b/lib/plist.c
index 3714969696..8091429e31 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
@@ -3157,6 +3156,40 @@ config_write_prefix_ipv4 (struct vty *vty)
}
static void
+plist_autocomplete_afi (afi_t afi, vector comps, struct cmd_token *token)
+{
+ struct prefix_list *plist;
+ struct prefix_master *master;
+
+ master = prefix_master_get (afi, 0);
+ if (master == NULL)
+ return;
+
+ for (plist = master->str.head; plist; plist = plist->next)
+ vector_set (comps, XSTRDUP (MTYPE_COMPLETION, plist->name));
+ for (plist = master->num.head; plist; plist = plist->next)
+ vector_set (comps, XSTRDUP (MTYPE_COMPLETION, plist->name));
+}
+
+static void
+plist_autocomplete(vector comps, struct cmd_token *token)
+{
+ plist_autocomplete_afi (AFI_IP, comps, token);
+ plist_autocomplete_afi (AFI_IP6, comps, token);
+}
+
+static const struct cmd_variable_handler plist_var_handlers[] = {
+ {
+ /* "prefix-list WORD" */
+ .varname = "prefix_list",
+ .completions = plist_autocomplete
+ }, {
+ .completions = NULL
+ }
+};
+
+
+static void
prefix_list_init_ipv4 (void)
{
install_node (&prefix_node, config_write_prefix_ipv4);
@@ -3275,6 +3308,8 @@ prefix_list_init_ipv6 (void)
void
prefix_list_init ()
{
+ cmd_variable_handler_register(plist_var_handlers);
+
prefix_list_init_ipv4 ();
prefix_list_init_ipv6 ();
}
diff --git a/lib/plist.h b/lib/plist.h
index 89d9a874f0..0f397ff01a 100644
--- a/lib/plist.h
+++ b/lib/plist.h
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _QUAGGA_PLIST_H
diff --git a/lib/plist_int.h b/lib/plist_int.h
index e6e5901dbf..e711d12564 100644
--- a/lib/plist_int.h
+++ b/lib/plist_int.h
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _QUAGGA_PLIST_INT_H
diff --git a/lib/pqueue.c b/lib/pqueue.c
index 0f870564da..2d9127b88e 100644
--- a/lib/pqueue.c
+++ b/lib/pqueue.c
@@ -1,22 +1,22 @@
/* Priority queue functions.
- Copyright (C) 2003 Yasuhiro Ohara
-
-This file is part of GNU Zebra.
-
-GNU Zebra is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published
-by the Free Software Foundation; either version 2, or (at your
-option) any later version.
-
-GNU Zebra is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Zebra; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+ * Copyright (C) 2003 Yasuhiro Ohara
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
#include <zebra.h>
@@ -188,3 +188,11 @@ pqueue_remove_at (int index, struct pqueue *queue)
trickle_down (index, queue);
}
}
+
+void
+pqueue_remove (void *data, struct pqueue *queue)
+{
+ for (int i = 0; i < queue->size; i++)
+ if (queue->array[i] == data)
+ pqueue_remove_at (i, queue);
+}
diff --git a/lib/pqueue.h b/lib/pqueue.h
index 8bb6961d86..d87d91fdc5 100644
--- a/lib/pqueue.h
+++ b/lib/pqueue.h
@@ -1,22 +1,22 @@
/* Priority queue functions.
- Copyright (C) 2003 Yasuhiro Ohara
-
-This file is part of GNU Zebra.
-
-GNU Zebra is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published
-by the Free Software Foundation; either version 2, or (at your
-option) any later version.
-
-GNU Zebra is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Zebra; see the file COPYING. If not, write to the
-Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+ * Copyright (C) 2003 Yasuhiro Ohara
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
#ifndef _ZEBRA_PQUEUE_H
#define _ZEBRA_PQUEUE_H
@@ -39,6 +39,7 @@ extern void pqueue_delete (struct pqueue *queue);
extern void pqueue_enqueue (void *data, struct pqueue *queue);
extern void *pqueue_dequeue (struct pqueue *queue);
extern void pqueue_remove_at (int index, struct pqueue *queue);
+extern void pqueue_remove (void *data, struct pqueue *queue);
extern void trickle_down (int index, struct pqueue *queue);
extern void trickle_up (int index, struct pqueue *queue);
diff --git a/lib/prefix.c b/lib/prefix.c
index 0cc759bb7c..9c228cf954 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
@@ -252,12 +251,14 @@ safi2str(safi_t safi)
return "unicast";
case SAFI_MULTICAST:
return "multicast";
- case SAFI_ENCAP:
- return "encap";
case SAFI_MPLS_VPN:
return "vpn";
+ case SAFI_ENCAP:
+ return "encap";
case SAFI_EVPN:
return "evpn";
+ case SAFI_LABELED_UNICAST:
+ return "labeled-unicast";
}
return NULL;
}
diff --git a/lib/prefix.h b/lib/prefix.h
index eb3ae3dafb..09cb0cab87 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_PREFIX_H
@@ -244,6 +243,8 @@ union prefixconstptr
/* Count prefix size from mask length */
#define PSIZE(a) (((a) + 7) / (8))
+#define BSIZE(a) ((a) * (8))
+
/* Prefix's family member. */
#define PREFIX_FAMILY(p) ((p)->family)
diff --git a/lib/privs.c b/lib/privs.c
index decd4bb7db..3a66382191 100644
--- a/lib/privs.c
+++ b/lib/privs.c
@@ -16,10 +16,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
#include "log.h"
@@ -769,6 +768,7 @@ zprivs_init(struct zebra_privs_t *zprivs)
}
}
+ zprivs_state.zsuid = geteuid(); /* initial uid */
/* add groups only if we changed uid - otherwise skip */
if ((ngroups) && (zprivs_state.zsuid != zprivs_state.zuid))
{
diff --git a/lib/privs.h b/lib/privs.h
index 46d614e008..9a5eb3bd6c 100644
--- a/lib/privs.h
+++ b/lib/privs.h
@@ -15,10 +15,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_PRIVS_H
diff --git a/lib/ptm_lib.c b/lib/ptm_lib.c
index a93d7b8476..7181e2d89d 100644
--- a/lib/ptm_lib.c
+++ b/lib/ptm_lib.c
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Quagga; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <stdlib.h>
diff --git a/lib/ptm_lib.h b/lib/ptm_lib.h
index be4170bb37..747ce349ad 100644
--- a/lib/ptm_lib.h
+++ b/lib/ptm_lib.h
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Quagga; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __PTM_LIB_H__
#define __PTM_LIB_H__
diff --git a/lib/qobj.c b/lib/qobj.c
index 8a386d2486..fd7b4c8c5b 100644
--- a/lib/qobj.c
+++ b/lib/qobj.c
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Quagga; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
diff --git a/lib/route_types.txt b/lib/route_types.txt
index 5cb06ffb7f..7625d1f690 100644
--- a/lib/route_types.txt
+++ b/lib/route_types.txt
@@ -52,6 +52,7 @@ ZEBRA_ROUTE_OSPF6, ospf6, ospf6d, 'O', 0, 1, "OSPFv3"
ZEBRA_ROUTE_ISIS, isis, isisd, 'I', 1, 1, "IS-IS"
ZEBRA_ROUTE_BGP, bgp, bgpd, 'B', 1, 1, "BGP"
ZEBRA_ROUTE_PIM, pim, pimd, 'P', 1, 0, "PIM"
+ZEBRA_ROUTE_EIGRP, eigrp, eigrpd, 'E', 1, 0, "EIGRP"
ZEBRA_ROUTE_NHRP, nhrp, nhrpd, 'N', 1, 1, "NHRP"
# HSLS and OLSR both are AFI independent (so: 1, 1), however
# we want to disable for them for general Quagga distribution.
@@ -86,6 +87,7 @@ ZEBRA_ROUTE_OSPF6, "Open Shortest Path First (IPv6) (OSPFv3)"
ZEBRA_ROUTE_ISIS, "Intermediate System to Intermediate System (IS-IS)"
ZEBRA_ROUTE_BGP, "Border Gateway Protocol (BGP)"
ZEBRA_ROUTE_PIM, "Protocol Independent Multicast (PIM)"
+ZEBRA_ROUTE_EIGRP, "Enhanced Interior Gateway Routing Protocol (EIGRP)"
ZEBRA_ROUTE_NHRP, "Next Hop Resolution Protocol (NHRP)"
ZEBRA_ROUTE_HSLS, "Hazy-Sighted Link State Protocol (HSLS)"
ZEBRA_ROUTE_VNC, "Virtual Network Control (VNC)"
diff --git a/lib/routemap.c b/lib/routemap.c
index cd34ffaae5..44b3c2bf9f 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -1,22 +1,22 @@
/* Route map function.
- Copyright (C) 1998, 1999 Kunihiro Ishiguro
-
-This file is part of GNU Zebra.
-
-GNU Zebra is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-GNU Zebra is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Zebra; see the file COPYING. If not, write to the Free
-Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+ * Copyright (C) 1998, 1999 Kunihiro Ishiguro
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
#include <zebra.h>
@@ -2001,7 +2001,7 @@ DEFUN (match_interface,
DEFUN (no_match_interface,
no_match_interface_cmd,
- "no match interface [INTERFACE]",
+ "no match interface [WORD]",
NO_STR
MATCH_STR
"Match first hop interface of route\n"
@@ -2958,6 +2958,30 @@ route_map_finish (void)
route_map_master_hash = NULL;
}
+static void rmap_autocomplete(vector comps, struct cmd_token *token)
+{
+ struct route_map *map;
+
+ for (map = route_map_master.head; map; map = map->next)
+ vector_set (comps, XSTRDUP (MTYPE_COMPLETION, map->name));
+}
+
+static const struct cmd_variable_handler rmap_var_handlers[] = {
+ {
+ /* "route-map WORD" */
+ .varname = "route_map",
+ .completions = rmap_autocomplete
+ }, {
+ .tokenname = "ROUTEMAP_NAME",
+ .completions = rmap_autocomplete
+ }, {
+ .tokenname = "RMAP_NAME",
+ .completions = rmap_autocomplete
+ }, {
+ .completions = NULL
+ }
+};
+
/* Initialization of route map vector. */
void
route_map_init (void)
@@ -2973,6 +2997,8 @@ route_map_init (void)
route_map_dep_hash[i] = hash_create(route_map_dep_hash_make_key,
route_map_dep_hash_cmp);
+ cmd_variable_handler_register(rmap_var_handlers);
+
/* Install route map top node. */
install_node (&rmap_node, route_map_config_write);
diff --git a/lib/routemap.h b/lib/routemap.h
index b378c64eae..f1937ac403 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_ROUTEMAP_H
diff --git a/lib/sha256.c b/lib/sha256.c
new file mode 100644
index 0000000000..f98a758821
--- /dev/null
+++ b/lib/sha256.c
@@ -0,0 +1,433 @@
+/*-
+ * Copyright 2005,2007,2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <zebra.h>
+#include "sha256.h"
+
+#if !HAVE_DECL_BE32DEC
+static inline uint32_t
+be32dec(const void *pp)
+{
+ const uint8_t *p = (uint8_t const *)pp;
+
+ return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) +
+ ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24));
+}
+#else
+#include <sys/endian.h>
+#endif
+
+#if !HAVE_DECL_BE32ENC
+static inline void
+be32enc(void *pp, uint32_t x)
+{
+ uint8_t * p = (uint8_t *)pp;
+
+ p[3] = x & 0xff;
+ p[2] = (x >> 8) & 0xff;
+ p[1] = (x >> 16) & 0xff;
+ p[0] = (x >> 24) & 0xff;
+}
+#else
+#include <sys/endian.h>
+#endif
+
+/*
+ * Encode a length len/4 vector of (uint32_t) into a length len vector of
+ * (unsigned char) in big-endian form. Assumes len is a multiple of 4.
+ */
+static void
+be32enc_vect(unsigned char *dst, const uint32_t *src, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len / 4; i++)
+ be32enc(dst + i * 4, src[i]);
+}
+
+/*
+ * Decode a big-endian length len vector of (unsigned char) into a length
+ * len/4 vector of (uint32_t). Assumes len is a multiple of 4.
+ */
+static void
+be32dec_vect(uint32_t *dst, const unsigned char *src, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len / 4; i++)
+ dst[i] = be32dec(src + i * 4);
+}
+
+/* Elementary functions used by SHA256 */
+#define Ch(x, y, z) ((x & (y ^ z)) ^ z)
+#define Maj(x, y, z) ((x & (y | z)) | (y & z))
+#define SHR(x, n) (x >> n)
+#define ROTR(x, n) ((x >> n) | (x << (32 - n)))
+#define S0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
+#define S1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
+#define s0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
+#define s1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
+
+/* SHA256 round function */
+#define RND(a, b, c, d, e, f, g, h, k) \
+ t0 = h + S1(e) + Ch(e, f, g) + k; \
+ t1 = S0(a) + Maj(a, b, c); \
+ d += t0; \
+ h = t0 + t1;
+
+/* Adjusted round function for rotating state */
+#define RNDr(S, W, i, k) \
+ RND(S[(64 - i) % 8], S[(65 - i) % 8], \
+ S[(66 - i) % 8], S[(67 - i) % 8], \
+ S[(68 - i) % 8], S[(69 - i) % 8], \
+ S[(70 - i) % 8], S[(71 - i) % 8], \
+ W[i] + k)
+
+/*
+ * SHA256 block compression function. The 256-bit state is transformed via
+ * the 512-bit input block to produce a new state.
+ */
+static void
+SHA256_Transform(uint32_t * state, const unsigned char block[64])
+{
+ uint32_t W[64];
+ uint32_t S[8];
+ uint32_t t0, t1;
+ int i;
+
+ /* 1. Prepare message schedule W. */
+ be32dec_vect(W, block, 64);
+ for (i = 16; i < 64; i++)
+ W[i] = s1(W[i - 2]) + W[i - 7] + s0(W[i - 15]) + W[i - 16];
+
+ /* 2. Initialize working variables. */
+ memcpy(S, state, 32);
+
+ /* 3. Mix. */
+ RNDr(S, W, 0, 0x428a2f98);
+ RNDr(S, W, 1, 0x71374491);
+ RNDr(S, W, 2, 0xb5c0fbcf);
+ RNDr(S, W, 3, 0xe9b5dba5);
+ RNDr(S, W, 4, 0x3956c25b);
+ RNDr(S, W, 5, 0x59f111f1);
+ RNDr(S, W, 6, 0x923f82a4);
+ RNDr(S, W, 7, 0xab1c5ed5);
+ RNDr(S, W, 8, 0xd807aa98);
+ RNDr(S, W, 9, 0x12835b01);
+ RNDr(S, W, 10, 0x243185be);
+ RNDr(S, W, 11, 0x550c7dc3);
+ RNDr(S, W, 12, 0x72be5d74);
+ RNDr(S, W, 13, 0x80deb1fe);
+ RNDr(S, W, 14, 0x9bdc06a7);
+ RNDr(S, W, 15, 0xc19bf174);
+ RNDr(S, W, 16, 0xe49b69c1);
+ RNDr(S, W, 17, 0xefbe4786);
+ RNDr(S, W, 18, 0x0fc19dc6);
+ RNDr(S, W, 19, 0x240ca1cc);
+ RNDr(S, W, 20, 0x2de92c6f);
+ RNDr(S, W, 21, 0x4a7484aa);
+ RNDr(S, W, 22, 0x5cb0a9dc);
+ RNDr(S, W, 23, 0x76f988da);
+ RNDr(S, W, 24, 0x983e5152);
+ RNDr(S, W, 25, 0xa831c66d);
+ RNDr(S, W, 26, 0xb00327c8);
+ RNDr(S, W, 27, 0xbf597fc7);
+ RNDr(S, W, 28, 0xc6e00bf3);
+ RNDr(S, W, 29, 0xd5a79147);
+ RNDr(S, W, 30, 0x06ca6351);
+ RNDr(S, W, 31, 0x14292967);
+ RNDr(S, W, 32, 0x27b70a85);
+ RNDr(S, W, 33, 0x2e1b2138);
+ RNDr(S, W, 34, 0x4d2c6dfc);
+ RNDr(S, W, 35, 0x53380d13);
+ RNDr(S, W, 36, 0x650a7354);
+ RNDr(S, W, 37, 0x766a0abb);
+ RNDr(S, W, 38, 0x81c2c92e);
+ RNDr(S, W, 39, 0x92722c85);
+ RNDr(S, W, 40, 0xa2bfe8a1);
+ RNDr(S, W, 41, 0xa81a664b);
+ RNDr(S, W, 42, 0xc24b8b70);
+ RNDr(S, W, 43, 0xc76c51a3);
+ RNDr(S, W, 44, 0xd192e819);
+ RNDr(S, W, 45, 0xd6990624);
+ RNDr(S, W, 46, 0xf40e3585);
+ RNDr(S, W, 47, 0x106aa070);
+ RNDr(S, W, 48, 0x19a4c116);
+ RNDr(S, W, 49, 0x1e376c08);
+ RNDr(S, W, 50, 0x2748774c);
+ RNDr(S, W, 51, 0x34b0bcb5);
+ RNDr(S, W, 52, 0x391c0cb3);
+ RNDr(S, W, 53, 0x4ed8aa4a);
+ RNDr(S, W, 54, 0x5b9cca4f);
+ RNDr(S, W, 55, 0x682e6ff3);
+ RNDr(S, W, 56, 0x748f82ee);
+ RNDr(S, W, 57, 0x78a5636f);
+ RNDr(S, W, 58, 0x84c87814);
+ RNDr(S, W, 59, 0x8cc70208);
+ RNDr(S, W, 60, 0x90befffa);
+ RNDr(S, W, 61, 0xa4506ceb);
+ RNDr(S, W, 62, 0xbef9a3f7);
+ RNDr(S, W, 63, 0xc67178f2);
+
+ /* 4. Mix local working variables into global state */
+ for (i = 0; i < 8; i++)
+ state[i] += S[i];
+
+ /* Clean the stack. */
+ memset(W, 0, 256);
+ memset(S, 0, 32);
+ t0 = t1 = 0;
+}
+
+static unsigned char PAD[64] = {
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* Add padding and terminating bit-count. */
+static void
+SHA256_Pad(SHA256_CTX * ctx)
+{
+ unsigned char len[8];
+ uint32_t r, plen;
+
+ /*
+ * Convert length to a vector of bytes -- we do this now rather
+ * than later because the length will change after we pad.
+ */
+ be32enc_vect(len, ctx->count, 8);
+
+ /* Add 1--64 bytes so that the resulting length is 56 mod 64 */
+ r = (ctx->count[1] >> 3) & 0x3f;
+ plen = (r < 56) ? (56 - r) : (120 - r);
+ SHA256_Update(ctx, PAD, (size_t)plen);
+
+ /* Add the terminating bit-count */
+ SHA256_Update(ctx, len, 8);
+}
+
+/* SHA-256 initialization. Begins a SHA-256 operation. */
+void
+SHA256_Init(SHA256_CTX * ctx)
+{
+
+ /* Zero bits processed so far */
+ ctx->count[0] = ctx->count[1] = 0;
+
+ /* Magic initialization constants */
+ ctx->state[0] = 0x6A09E667;
+ ctx->state[1] = 0xBB67AE85;
+ ctx->state[2] = 0x3C6EF372;
+ ctx->state[3] = 0xA54FF53A;
+ ctx->state[4] = 0x510E527F;
+ ctx->state[5] = 0x9B05688C;
+ ctx->state[6] = 0x1F83D9AB;
+ ctx->state[7] = 0x5BE0CD19;
+}
+
+/* Add bytes into the hash */
+void
+SHA256_Update(SHA256_CTX * ctx, const void *in, size_t len)
+{
+ uint32_t bitlen[2];
+ uint32_t r;
+ const unsigned char *src = in;
+
+ /* Number of bytes left in the buffer from previous updates */
+ r = (ctx->count[1] >> 3) & 0x3f;
+
+ /* Convert the length into a number of bits */
+ bitlen[1] = ((uint32_t)len) << 3;
+ bitlen[0] = (uint32_t)(len >> 29);
+
+ /* Update number of bits */
+ if ((ctx->count[1] += bitlen[1]) < bitlen[1])
+ ctx->count[0]++;
+ ctx->count[0] += bitlen[0];
+
+ /* Handle the case where we don't need to perform any transforms */
+ if (len < 64 - r) {
+ memcpy(&ctx->buf[r], src, len);
+ return;
+ }
+
+ /* Finish the current block */
+ memcpy(&ctx->buf[r], src, 64 - r);
+ SHA256_Transform(ctx->state, ctx->buf);
+ src += 64 - r;
+ len -= 64 - r;
+
+ /* Perform complete blocks */
+ while (len >= 64) {
+ SHA256_Transform(ctx->state, src);
+ src += 64;
+ len -= 64;
+ }
+
+ /* Copy left over data into buffer */
+ memcpy(ctx->buf, src, len);
+}
+
+/*
+ * SHA-256 finalization. Pads the input data, exports the hash value,
+ * and clears the context state.
+ */
+void
+SHA256_Final(unsigned char digest[32], SHA256_CTX * ctx)
+{
+
+ /* Add padding */
+ SHA256_Pad(ctx);
+
+ /* Write the hash */
+ be32enc_vect(digest, ctx->state, 32);
+
+ /* Clear the context state */
+ memset((void *)ctx, 0, sizeof(*ctx));
+}
+
+/* Initialize an HMAC-SHA256 operation with the given key. */
+void
+HMAC__SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen)
+{
+ unsigned char pad[64];
+ unsigned char khash[32];
+ const unsigned char * K = _K;
+ size_t i;
+
+ /* If Klen > 64, the key is really SHA256(K). */
+ if (Klen > 64) {
+ SHA256_Init(&ctx->ictx);
+ SHA256_Update(&ctx->ictx, K, Klen);
+ SHA256_Final(khash, &ctx->ictx);
+ K = khash;
+ Klen = 32;
+ }
+
+ /* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */
+ SHA256_Init(&ctx->ictx);
+ memset(pad, 0x36, 64);
+ for (i = 0; i < Klen; i++)
+ pad[i] ^= K[i];
+ SHA256_Update(&ctx->ictx, pad, 64);
+
+ /* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */
+ SHA256_Init(&ctx->octx);
+ memset(pad, 0x5c, 64);
+ for (i = 0; i < Klen; i++)
+ pad[i] ^= K[i];
+ SHA256_Update(&ctx->octx, pad, 64);
+
+ /* Clean the stack. */
+ memset(khash, 0, 32);
+}
+
+/* Add bytes to the HMAC-SHA256 operation. */
+void
+HMAC__SHA256_Update(HMAC_SHA256_CTX * ctx, const void *in, size_t len)
+{
+
+ /* Feed data to the inner SHA256 operation. */
+ SHA256_Update(&ctx->ictx, in, len);
+}
+
+/* Finish an HMAC-SHA256 operation. */
+void
+HMAC__SHA256_Final(unsigned char digest[32], HMAC_SHA256_CTX * ctx)
+{
+ unsigned char ihash[32];
+
+ /* Finish the inner SHA256 operation. */
+ SHA256_Final(ihash, &ctx->ictx);
+
+ /* Feed the inner hash to the outer SHA256 operation. */
+ SHA256_Update(&ctx->octx, ihash, 32);
+
+ /* Finish the outer SHA256 operation. */
+ SHA256_Final(digest, &ctx->octx);
+
+ /* Clean the stack. */
+ memset(ihash, 0, 32);
+}
+
+/**
+ * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
+ * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
+ * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
+ */
+void
+PBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,
+ size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen)
+{
+ HMAC_SHA256_CTX PShctx, hctx;
+ size_t i;
+ uint8_t ivec[4];
+ uint8_t U[32];
+ uint8_t T[32];
+ uint64_t j;
+ int k;
+ size_t clen;
+
+ /* Compute HMAC state after processing P and S. */
+ HMAC__SHA256_Init(&PShctx, passwd, passwdlen);
+ HMAC__SHA256_Update(&PShctx, salt, saltlen);
+
+ /* Iterate through the blocks. */
+ for (i = 0; i * 32 < dkLen; i++) {
+ /* Generate INT(i + 1). */
+ be32enc(ivec, (uint32_t)(i + 1));
+
+ /* Compute U_1 = PRF(P, S || INT(i)). */
+ memcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX));
+ HMAC__SHA256_Update(&hctx, ivec, 4);
+ HMAC__SHA256_Final(U, &hctx);
+
+ /* T_i = U_1 ... */
+ memcpy(T, U, 32);
+
+ for (j = 2; j <= c; j++) {
+ /* Compute U_j. */
+ HMAC__SHA256_Init(&hctx, passwd, passwdlen);
+ HMAC__SHA256_Update(&hctx, U, 32);
+ HMAC__SHA256_Final(U, &hctx);
+
+ /* ... xor U_j ... */
+ for (k = 0; k < 32; k++)
+ T[k] ^= U[k];
+ }
+
+ /* Copy as many bytes as necessary into buf. */
+ clen = dkLen - i * 32;
+ if (clen > 32)
+ clen = 32;
+ memcpy(&buf[i * 32], T, clen);
+ }
+
+ /* Clean PShctx, since we never called _Final on it. */
+ memset(&PShctx, 0, sizeof(HMAC_SHA256_CTX));
+}
diff --git a/lib/sha256.h b/lib/sha256.h
new file mode 100644
index 0000000000..502f3fc224
--- /dev/null
+++ b/lib/sha256.h
@@ -0,0 +1,58 @@
+/*-
+ * Copyright 2005,2007,2009 Colin Percival
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/lib/libmd/sha256.h,v 1.2 2006/01/17 15:35:56 phk Exp $
+ */
+
+#ifndef _SHA256_H_
+#define _SHA256_H_
+
+typedef struct SHA256Context {
+ uint32_t state[8];
+ uint32_t count[2];
+ unsigned char buf[64];
+} SHA256_CTX;
+
+typedef struct HMAC_SHA256Context {
+ SHA256_CTX ictx;
+ SHA256_CTX octx;
+} HMAC_SHA256_CTX;
+
+void SHA256_Init(SHA256_CTX *);
+void SHA256_Update(SHA256_CTX *, const void *, size_t);
+void SHA256_Final(unsigned char [32], SHA256_CTX *);
+void HMAC__SHA256_Init(HMAC_SHA256_CTX *, const void *, size_t);
+void HMAC__SHA256_Update(HMAC_SHA256_CTX *, const void *, size_t);
+void HMAC__SHA256_Final(unsigned char [32], HMAC_SHA256_CTX *);
+
+/**
+ * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):
+ * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and
+ * write the output to buf. The value dkLen must be at most 32 * (2^32 - 1).
+ */
+void PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t,
+ uint64_t, uint8_t *, size_t);
+
+#endif /* !_SHA256_H_ */
diff --git a/lib/sigevent.c b/lib/sigevent.c
index 09f07180ce..e8c722b987 100644
--- a/lib/sigevent.c
+++ b/lib/sigevent.c
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Quagga; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
@@ -132,8 +131,9 @@ quagga_signal_timer (struct thread *t)
int i;
sigm = THREAD_ARG (t);
- sigm->t = thread_add_timer (sigm->t->master, quagga_signal_timer, &sigmaster,
- QUAGGA_SIGNAL_TIMER_INTERVAL);
+ sigm->t = NULL;
+ thread_add_timer(sigm->t->master, quagga_signal_timer, &sigmaster, QUAGGA_SIGNAL_TIMER_INTERVAL,
+ &sigm->t);
return quagga_sigevent_process ();
}
#endif /* SIGEVENT_SCHEDULE_THREAD */
@@ -233,6 +233,18 @@ core_handler(int signo
#endif
)
{
+ /* make sure we don't hang in here. default for SIGALRM is terminate.
+ * - if we're in backtrace for more than a second, abort. */
+ struct sigaction sa_default = { .sa_handler = SIG_DFL };
+ sigaction (SIGALRM, &sa_default, NULL);
+
+ sigset_t sigset;
+ sigemptyset (&sigset);
+ sigaddset (&sigset, SIGALRM);
+ sigprocmask (SIG_UNBLOCK, &sigset, NULL);
+
+ alarm (1);
+
zlog_signal(signo, "aborting..."
#ifdef SA_SIGINFO
, siginfo, program_counter(context)
@@ -327,6 +339,11 @@ trap_default_signals(void)
act.sa_handler = sigmap[i].handler;
act.sa_flags = 0;
#endif
+#ifdef SA_RESETHAND
+ /* don't try to print backtraces recursively */
+ if (sigmap[i].handler == core_handler)
+ act.sa_flags |= SA_RESETHAND;
+#endif
}
if (sigaction(sigmap[i].sigs[j],&act,NULL) < 0)
zlog_warn("Unable to set signal handler for signal %d: %s",
@@ -361,8 +378,8 @@ signal_init (struct thread_master *m, int sigc,
sigmaster.signals = signals;
#ifdef SIGEVENT_SCHEDULE_THREAD
- sigmaster.t =
- thread_add_timer (m, quagga_signal_timer, &sigmaster,
- QUAGGA_SIGNAL_TIMER_INTERVAL);
+ sigmaster.t = NULL;
+ thread_add_timer(m, quagga_signal_timer, &sigmaster, QUAGGA_SIGNAL_TIMER_INTERVAL,
+ &sigmaster.t);
#endif /* SIGEVENT_SCHEDULE_THREAD */
}
diff --git a/lib/sigevent.h b/lib/sigevent.h
index 248fa2c058..08eb1ca412 100644
--- a/lib/sigevent.h
+++ b/lib/sigevent.h
@@ -15,10 +15,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Quagga; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _QUAGGA_SIGNAL_H
diff --git a/lib/smux.c b/lib/smux.c
index 370b8f138e..032801f6df 100644
--- a/lib/smux.c
+++ b/lib/smux.c
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
@@ -1197,13 +1196,18 @@ smux_event (enum smux_event event, int sock)
switch (event)
{
case SMUX_SCHEDULE:
- smux_connect_thread = thread_add_event (smux_master, smux_connect, NULL, 0);
+ smux_connect_thread = NULL;
+ thread_add_event(smux_master, smux_connect, NULL, 0,
+ &smux_connect_thread);
break;
case SMUX_CONNECT:
- smux_connect_thread = thread_add_timer (smux_master, smux_connect, NULL, 10);
+ smux_connect_thread = NULL;
+ thread_add_timer(smux_master, smux_connect, NULL, 10,
+ &smux_connect_thread);
break;
case SMUX_READ:
- smux_read_thread = thread_add_read (smux_master, smux_read, NULL, sock);
+ smux_read_thread = NULL;
+ thread_add_read(smux_master, smux_read, NULL, sock, &smux_read_thread);
break;
default:
break;
diff --git a/lib/smux.h b/lib/smux.h
index dc91cac71a..e94a7a9cc9 100644
--- a/lib/smux.h
+++ b/lib/smux.h
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_SNMP_H
diff --git a/lib/snmp.c b/lib/snmp.c
index 1cbd41c720..7eb86e9412 100644
--- a/lib/snmp.c
+++ b/lib/snmp.c
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
diff --git a/lib/sockopt.c b/lib/sockopt.c
index 2a9f907cb3..83ea574833 100644
--- a/lib/sockopt.c
+++ b/lib/sockopt.c
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
diff --git a/lib/sockopt.h b/lib/sockopt.h
index 1b7be1e49f..d31fcaa411 100644
--- a/lib/sockopt.h
+++ b/lib/sockopt.h
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_SOCKOPT_H
diff --git a/lib/sockunion.c b/lib/sockunion.c
index 9ba2ce82f6..423ad20441 100644
--- a/lib/sockunion.c
+++ b/lib/sockunion.c
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
diff --git a/lib/sockunion.h b/lib/sockunion.h
index bed68e1ee1..98c3e0adef 100644
--- a/lib/sockunion.h
+++ b/lib/sockunion.h
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_SOCKUNION_H
diff --git a/lib/spf_backoff.c b/lib/spf_backoff.c
index e923f232b8..7e34947344 100644
--- a/lib/spf_backoff.c
+++ b/lib/spf_backoff.c
@@ -19,10 +19,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with FRR; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
@@ -169,21 +168,19 @@ long spf_backoff_schedule(struct spf_backoff *backoff)
{
case SPF_BACKOFF_QUIET:
backoff->state = SPF_BACKOFF_SHORT_WAIT;
- THREAD_TIMER_MSEC_ON(backoff->m, backoff->t_timetolearn,
- spf_backoff_timetolearn_elapsed, backoff,
- backoff->timetolearn);
- THREAD_TIMER_MSEC_ON(backoff->m, backoff->t_holddown,
- spf_backoff_holddown_elapsed, backoff,
- backoff->holddown);
+ thread_add_timer_msec(backoff->m, spf_backoff_timetolearn_elapsed,
+ backoff, backoff->timetolearn,
+ &backoff->t_timetolearn);
+ thread_add_timer_msec(backoff->m, spf_backoff_holddown_elapsed, backoff,
+ backoff->holddown, &backoff->t_holddown);
backoff->first_event_time = now;
rv = backoff->init_delay;
break;
case SPF_BACKOFF_SHORT_WAIT:
case SPF_BACKOFF_LONG_WAIT:
THREAD_TIMER_OFF(backoff->t_holddown);
- THREAD_TIMER_MSEC_ON(backoff->m, backoff->t_holddown,
- spf_backoff_holddown_elapsed, backoff,
- backoff->holddown);
+ thread_add_timer_msec(backoff->m, spf_backoff_holddown_elapsed, backoff,
+ backoff->holddown, &backoff->t_holddown);
if (backoff->state == SPF_BACKOFF_SHORT_WAIT)
rv = backoff->short_delay;
else
diff --git a/lib/spf_backoff.h b/lib/spf_backoff.h
index 552ca4ae41..92bd46506a 100644
--- a/lib/spf_backoff.h
+++ b/lib/spf_backoff.h
@@ -19,10 +19,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with FRR; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_SPF_BACKOFF_H
#define _ZEBRA_SPF_BACKOFF_H
diff --git a/lib/srcdest_table.c b/lib/srcdest_table.c
index 04c9eff79a..383cf00d4f 100644
--- a/lib/srcdest_table.c
+++ b/lib/srcdest_table.c
@@ -16,10 +16,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with FRR; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
diff --git a/lib/srcdest_table.h b/lib/srcdest_table.h
index 207f5d121d..0d858d11ab 100644
--- a/lib/srcdest_table.h
+++ b/lib/srcdest_table.h
@@ -16,10 +16,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with FRR; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_SRC_DEST_TABLE_H
diff --git a/lib/stream.c b/lib/stream.c
index 301ebc6275..e8320a8fa1 100644
--- a/lib/stream.c
+++ b/lib/stream.c
@@ -1,4 +1,4 @@
- /*
+/*
* Packet interface
* Copyright (C) 1999 Kunihiro Ishiguro
*
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
@@ -919,6 +918,31 @@ stream_put_prefix (struct stream *s, struct prefix *p)
return stream_put_prefix_addpath (s, p, 0, 0);
}
+/* Put NLRI with label */
+int
+stream_put_labeled_prefix (struct stream *s, struct prefix *p, u_char *label)
+{
+ size_t psize;
+
+ STREAM_VERIFY_SANE(s);
+
+ psize = PSIZE (p->prefixlen);
+
+ if (STREAM_WRITEABLE (s) < (psize + 3))
+ {
+ STREAM_BOUND_WARN (s, "put");
+ return 0;
+ }
+
+ stream_putc (s, (p->prefixlen + 24));
+ stream_putc(s, label[0]);
+ stream_putc(s, label[1]);
+ stream_putc(s, label[2]);
+ memcpy (s->data + s->endp, &p->u.prefix, psize);
+ s->endp += psize;
+
+ return (psize + 3);
+}
/* Read size from fd. */
int
diff --git a/lib/stream.h b/lib/stream.h
index 1e2bc89b32..dd6aae677d 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_STREAM_H
@@ -181,7 +180,8 @@ extern int stream_put_prefix_addpath (struct stream *, struct prefix *,
int addpath_encode,
u_int32_t addpath_tx_id);
extern int stream_put_prefix (struct stream *, struct prefix *);
-
+extern int stream_put_labeled_prefix (struct stream *, struct prefix *,
+ u_char *);
extern void stream_get (void *, struct stream *, size_t);
extern void stream_get_from (void *, struct stream *, size_t, size_t);
extern u_char stream_getc (struct stream *);
diff --git a/lib/strlcat.c b/lib/strlcat.c
index 1d04b43d95..6fdb2a4a37 100644
--- a/lib/strlcat.c
+++ b/lib/strlcat.c
@@ -1,20 +1,21 @@
/* Append a null-terminated string to another string, with length checking.
- Copyright (C) 2016 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
+ * Copyright (C) 2016 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ *
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * The GNU C Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the GNU C Library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
/* adapted for Quagga from glibc patch submission originally from
* Florian Weimer <fweimer@redhat.com>, 2016-05-18 */
diff --git a/lib/strlcpy.c b/lib/strlcpy.c
index 41bab97ea7..112c8180b9 100644
--- a/lib/strlcpy.c
+++ b/lib/strlcpy.c
@@ -1,20 +1,21 @@
/* Copy a null-terminated string to a fixed-size buffer, with length checking.
- Copyright (C) 2016 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
+ * Copyright (C) 2016 Free Software Foundation, Inc.
+ * This file is part of the GNU C Library.
+ *
+ * The GNU C Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * The GNU C Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the GNU C Library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
/* adapted for Quagga from glibc patch submission originally from
* Florian Weimer <fweimer@redhat.com>, 2016-05-18 */
diff --git a/lib/systemd.c b/lib/systemd.c
index 4c78cf328c..341de9eabe 100644
--- a/lib/systemd.c
+++ b/lib/systemd.c
@@ -1,23 +1,23 @@
/* lib/systemd Code
- Copyright (C) 2016 Cumulus Networks, Inc.
- Donald Sharp
-
-This file is part of Quagga.
-
-Quagga is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-Quagga is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quagga; see the file COPYING. If not, write to the Free
-Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+ * Copyright (C) 2016 Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * This file is part of Quagga.
+ *
+ * Quagga is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * Quagga is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
#include <zebra.h>
@@ -104,7 +104,7 @@ systemd_send_watchdog (struct thread *t)
{
systemd_send_information ("WATCHDOG=1");
- thread_add_timer (systemd_master, systemd_send_watchdog, NULL, wsecs);
+ thread_add_timer(systemd_master, systemd_send_watchdog, NULL, wsecs, NULL);
return 1;
}
@@ -119,5 +119,5 @@ systemd_send_started (struct thread_master *m, int the_process)
systemd_send_information ("READY=1");
if (wsecs != 0)
- thread_add_timer (m, systemd_send_watchdog, m, wsecs);
+ thread_add_timer(m, systemd_send_watchdog, m, wsecs, NULL);
}
diff --git a/lib/systemd.h b/lib/systemd.h
index 685f3d9a77..c048797cf2 100644
--- a/lib/systemd.h
+++ b/lib/systemd.h
@@ -1,23 +1,23 @@
/* lib/systemd Code
- Copyright (C) 2016 Cumulus Networks, Inc.
- Donald Sharp
-
-This file is part of Quagga.
-
-Quagga is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-Quagga is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with Quagga; see the file COPYING. If not, write to the Free
-Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+ * Copyright (C) 2016 Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * This file is part of Quagga.
+ *
+ * Quagga is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * Quagga is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
/*
* Wrapper functions to systemd calls.
diff --git a/lib/table.c b/lib/table.c
index 7f789dd3cd..1461bb81a4 100644
--- a/lib/table.c
+++ b/lib/table.c
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
diff --git a/lib/table.h b/lib/table.h
index 1691a8e20a..00131b29c6 100644
--- a/lib/table.h
+++ b/lib/table.h
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_TABLE_H
diff --git a/lib/thread.c b/lib/thread.c
index dbdd91dd24..2843a9211e 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* #define DEBUG */
@@ -41,7 +40,7 @@ DEFINE_MTYPE_STATIC(LIB, THREAD_STATS, "Thread stats")
#include <mach/mach_time.h>
#endif
-/* Relative time, since startup */
+static pthread_mutex_t cpu_record_mtx = PTHREAD_MUTEX_INITIALIZER;
static struct hash *cpu_record = NULL;
static unsigned long
@@ -137,9 +136,14 @@ cpu_record_print(struct vty *vty, thread_type filter)
vty_out(vty, "Active Runtime(ms) Invoked Avg uSec Max uSecs");
vty_out(vty, " Avg uSec Max uSecs");
vty_out(vty, " Type Thread%s", VTY_NEWLINE);
- hash_iterate(cpu_record,
- (void(*)(struct hash_backet*,void*))cpu_record_hash_print,
- args);
+
+ pthread_mutex_lock (&cpu_record_mtx);
+ {
+ hash_iterate(cpu_record,
+ (void(*)(struct hash_backet*,void*))cpu_record_hash_print,
+ args);
+ }
+ pthread_mutex_unlock (&cpu_record_mtx);
if (tmp.total_calls > 0)
vty_out_cpu_thread_history(vty, &tmp);
@@ -216,16 +220,25 @@ cpu_record_hash_clear (struct hash_backet *bucket,
if ( !(a->types & *filter) )
return;
- hash_release (cpu_record, bucket->data);
+ pthread_mutex_lock (&cpu_record_mtx);
+ {
+ hash_release (cpu_record, bucket->data);
+ }
+ pthread_mutex_unlock (&cpu_record_mtx);
}
static void
cpu_record_clear (thread_type filter)
{
thread_type *tmp = &filter;
- hash_iterate (cpu_record,
- (void (*) (struct hash_backet*,void*)) cpu_record_hash_clear,
- tmp);
+
+ pthread_mutex_lock (&cpu_record_mtx);
+ {
+ hash_iterate (cpu_record,
+ (void (*) (struct hash_backet*,void*)) cpu_record_hash_clear,
+ tmp);
+ }
+ pthread_mutex_unlock (&cpu_record_mtx);
}
DEFUN (clear_thread_cpu,
@@ -326,16 +339,20 @@ thread_master_create (void)
getrlimit(RLIMIT_NOFILE, &limit);
- if (cpu_record == NULL)
- cpu_record
- = hash_create ((unsigned int (*) (void *))cpu_record_hash_key,
- (int (*) (const void *, const void *))cpu_record_hash_cmp);
+ pthread_mutex_lock (&cpu_record_mtx);
+ {
+ if (cpu_record == NULL)
+ cpu_record = hash_create ((unsigned int (*) (void *))cpu_record_hash_key,
+ (int (*) (const void *, const void *))
+ cpu_record_hash_cmp);
+ }
+ pthread_mutex_unlock (&cpu_record_mtx);
rv = XCALLOC (MTYPE_THREAD_MASTER, sizeof (struct thread_master));
if (rv == NULL)
- {
- return NULL;
- }
+ return NULL;
+
+ pthread_mutex_init (&rv->mtx, NULL);
rv->fd_limit = (int)limit.rlim_cur;
rv->read = XCALLOC (MTYPE_THREAD, sizeof (struct thread *) * rv->fd_limit);
@@ -358,6 +375,8 @@ thread_master_create (void)
rv->background = pqueue_create();
rv->timer->cmp = rv->background->cmp = thread_timer_cmp;
rv->timer->update = rv->background->update = thread_timer_update;
+ rv->spin = true;
+ rv->handle_signals = true;
#if defined(HAVE_POLL_CALL)
rv->handler.pfdsize = rv->fd_limit;
@@ -434,6 +453,7 @@ thread_add_unuse (struct thread_master *m, struct thread *thread)
assert (m != NULL && thread != NULL);
assert (thread->next == NULL);
assert (thread->prev == NULL);
+ thread->ref = NULL;
thread->type = THREAD_UNUSED;
thread->hist->total_active--;
@@ -498,11 +518,16 @@ thread_queue_free (struct thread_master *m, struct pqueue *queue)
void
thread_master_free_unused (struct thread_master *m)
{
- struct thread *t;
- while ((t = thread_trim_head(&m->unuse)) != NULL)
- {
- XFREE(MTYPE_THREAD, t);
- }
+ pthread_mutex_lock (&m->mtx);
+ {
+ struct thread *t;
+ while ((t = thread_trim_head(&m->unuse)) != NULL)
+ {
+ pthread_mutex_destroy (&t->mtx);
+ XFREE(MTYPE_THREAD, t);
+ }
+ }
+ pthread_mutex_unlock (&m->mtx);
}
/* Stop thread scheduler. */
@@ -516,25 +541,37 @@ thread_master_free (struct thread_master *m)
thread_list_free (m, &m->ready);
thread_list_free (m, &m->unuse);
thread_queue_free (m, m->background);
+ pthread_mutex_destroy (&m->mtx);
#if defined(HAVE_POLL_CALL)
XFREE (MTYPE_THREAD_MASTER, m->handler.pfds);
#endif
XFREE (MTYPE_THREAD_MASTER, m);
- if (cpu_record)
- {
- hash_clean (cpu_record, cpu_record_hash_free);
- hash_free (cpu_record);
- cpu_record = NULL;
- }
+ pthread_mutex_lock (&cpu_record_mtx);
+ {
+ if (cpu_record)
+ {
+ hash_clean (cpu_record, cpu_record_hash_free);
+ hash_free (cpu_record);
+ cpu_record = NULL;
+ }
+ }
+ pthread_mutex_unlock (&cpu_record_mtx);
}
/* Return remain time in second. */
unsigned long
thread_timer_remain_second (struct thread *thread)
{
- int64_t remain = monotime_until(&thread->u.sands, NULL) / 1000000LL;
+ int64_t remain;
+
+ pthread_mutex_lock (&thread->mtx);
+ {
+ remain = monotime_until(&thread->u.sands, NULL) / 1000000LL;
+ }
+ pthread_mutex_unlock (&thread->mtx);
+
return remain < 0 ? 0 : remain;
}
@@ -545,7 +582,11 @@ struct timeval
thread_timer_remain(struct thread *thread)
{
struct timeval remain;
- monotime_until(&thread->u.sands, &remain);
+ pthread_mutex_lock (&thread->mtx);
+ {
+ monotime_until(&thread->u.sands, &remain);
+ }
+ pthread_mutex_unlock (&thread->mtx);
return remain;
}
@@ -560,14 +601,18 @@ thread_get (struct thread_master *m, u_char type,
if (! thread)
{
thread = XCALLOC (MTYPE_THREAD, sizeof (struct thread));
+ /* mutex only needs to be initialized at struct creation. */
+ pthread_mutex_init (&thread->mtx, NULL);
m->alloc++;
}
+
thread->type = type;
thread->add_type = type;
thread->master = m;
thread->arg = arg;
thread->index = -1;
thread->yield = THREAD_YIELD_TIME_SLOT; /* default */
+ thread->ref = NULL;
/*
* So if the passed in funcname is not what we have
@@ -584,8 +629,12 @@ thread_get (struct thread_master *m, u_char type,
{
tmp.func = func;
tmp.funcname = funcname;
- thread->hist = hash_get (cpu_record, &tmp,
- (void * (*) (void *))cpu_record_hash_alloc);
+ pthread_mutex_lock (&cpu_record_mtx);
+ {
+ thread->hist = hash_get (cpu_record, &tmp,
+ (void * (*) (void *))cpu_record_hash_alloc);
+ }
+ pthread_mutex_unlock (&cpu_record_mtx);
}
thread->hist->total_active++;
thread->func = func;
@@ -650,15 +699,46 @@ static int
fd_select (struct thread_master *m, int size, thread_fd_set *read, thread_fd_set *write, thread_fd_set *except, struct timeval *timer_wait)
{
int num;
+
+ /* If timer_wait is null here, that means either select() or poll() should
+ * block indefinitely, unless the thread_master has overriden it. select()
+ * and poll() differ in the timeout values they interpret as an indefinite
+ * block; select() requires a null pointer, while poll takes a millisecond
+ * value of -1.
+ *
+ * The thread_master owner has the option of overriding the default behavior
+ * by setting ->selectpoll_timeout. If the value is positive, it specifies
+ * the maximum number of milliseconds to wait. If the timeout is -1, it
+ * specifies that we should never wait and always return immediately even if
+ * no event is detected. If the value is zero, the behavior is default.
+ */
+
#if defined(HAVE_POLL_CALL)
- /* recalc timeout for poll. Attention NULL pointer is no timeout with
- select, where with poll no timeount is -1 */
int timeout = -1;
- if (timer_wait != NULL)
+
+ if (timer_wait != NULL && m->selectpoll_timeout == 0) // use the default value
timeout = (timer_wait->tv_sec*1000) + (timer_wait->tv_usec/1000);
+ else if (m->selectpoll_timeout > 0) // use the user's timeout
+ timeout = m->selectpoll_timeout;
+ else if (m->selectpoll_timeout < 0) // effect a poll (return immediately)
+ timeout = 0;
num = poll (m->handler.pfds, m->handler.pfdcount + m->handler.pfdcountsnmp, timeout);
#else
+ struct timeval timeout;
+
+ if (m->selectpoll_timeout > 0) // use the user's timeout
+ {
+ timeout.tv_sec = m->selectpoll_timeout / 1000;
+ timeout.tv_usec = (m->selectpoll_timeout % 1000) * 1000;
+ timer_wait = &timeout;
+ }
+ else if (m->selectpoll_timeout < 0) // effect a poll (return immediately)
+ {
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ timer_wait = &timeout;
+ }
num = select (size, read, write, except, timer_wait);
#endif
@@ -698,52 +778,74 @@ fd_clear_read_write (struct thread *thread)
/* Add new read thread. */
struct thread *
funcname_thread_add_read_write (int dir, struct thread_master *m,
- int (*func) (struct thread *), void *arg, int fd,
- debugargdef)
+ int (*func) (struct thread *), void *arg, int fd, struct thread **t_ptr,
+ debugargdef)
{
struct thread *thread = NULL;
-#if !defined(HAVE_POLL_CALL)
- thread_fd_set *fdset = NULL;
- if (dir == THREAD_READ)
- fdset = &m->handler.readfd;
- else
- fdset = &m->handler.writefd;
-#endif
+ pthread_mutex_lock (&m->mtx);
+ {
+ if (t_ptr && *t_ptr) // thread is already scheduled; don't reschedule
+ {
+ pthread_mutex_unlock (&m->mtx);
+ return NULL;
+ }
#if defined (HAVE_POLL_CALL)
- thread = generic_thread_add(m, func, arg, fd, dir, debugargpass);
-
- if (thread == NULL)
- return NULL;
+ thread = generic_thread_add(m, func, arg, fd, dir, debugargpass);
#else
- if (FD_ISSET (fd, fdset))
- {
- zlog_warn ("There is already %s fd [%d]",
- (dir == THREAD_READ) ? "read" : "write", fd);
- return NULL;
- }
+ if (fd >= FD_SETSIZE)
+ {
+ zlog_err ("File descriptor %d is >= FD_SETSIZE (%d). Please recompile"
+ "with --enable-poll=yes", fd, FD_SETSIZE);
+ assert (fd < FD_SETSIZE && !"fd >= FD_SETSIZE");
+ }
+ thread_fd_set *fdset = NULL;
+ if (dir == THREAD_READ)
+ fdset = &m->handler.readfd;
+ else
+ fdset = &m->handler.writefd;
- FD_SET (fd, fdset);
- thread = thread_get (m, dir, func, arg, debugargpass);
+ if (FD_ISSET (fd, fdset))
+ {
+ zlog_warn ("There is already %s fd [%d]",
+ (dir == THREAD_READ) ? "read" : "write", fd);
+ }
+ else
+ {
+ FD_SET (fd, fdset);
+ thread = thread_get (m, dir, func, arg, debugargpass);
+ }
#endif
- thread->u.fd = fd;
- if (dir == THREAD_READ)
- thread_add_fd (m->read, thread);
- else
- thread_add_fd (m->write, thread);
+ if (thread)
+ {
+ pthread_mutex_lock (&thread->mtx);
+ {
+ thread->u.fd = fd;
+ if (dir == THREAD_READ)
+ thread_add_fd (m->read, thread);
+ else
+ thread_add_fd (m->write, thread);
+ }
+ pthread_mutex_unlock (&thread->mtx);
+
+ if (t_ptr)
+ {
+ *t_ptr = thread;
+ thread->ref = t_ptr;
+ }
+ }
+ }
+ pthread_mutex_unlock (&m->mtx);
return thread;
}
static struct thread *
funcname_thread_add_timer_timeval (struct thread_master *m,
- int (*func) (struct thread *),
- int type,
- void *arg,
- struct timeval *time_relative,
- debugargdef)
+ int (*func) (struct thread *), int type, void *arg,
+ struct timeval *time_relative, struct thread **t_ptr, debugargdef)
{
struct thread *thread;
struct pqueue *queue;
@@ -753,13 +855,32 @@ funcname_thread_add_timer_timeval (struct thread_master *m,
assert (type == THREAD_TIMER || type == THREAD_BACKGROUND);
assert (time_relative);
- queue = ((type == THREAD_TIMER) ? m->timer : m->background);
- thread = thread_get (m, type, func, arg, debugargpass);
+ pthread_mutex_lock (&m->mtx);
+ {
+ if (t_ptr && *t_ptr) // thread is already scheduled; don't reschedule
+ {
+ pthread_mutex_unlock (&m->mtx);
+ return NULL;
+ }
- monotime(&thread->u.sands);
- timeradd(&thread->u.sands, time_relative, &thread->u.sands);
+ queue = ((type == THREAD_TIMER) ? m->timer : m->background);
+ thread = thread_get (m, type, func, arg, debugargpass);
+
+ pthread_mutex_lock (&thread->mtx);
+ {
+ monotime(&thread->u.sands);
+ timeradd(&thread->u.sands, time_relative, &thread->u.sands);
+ pqueue_enqueue(thread, queue);
+ if (t_ptr)
+ {
+ *t_ptr = thread;
+ thread->ref = t_ptr;
+ }
+ }
+ pthread_mutex_unlock (&thread->mtx);
+ }
+ pthread_mutex_unlock (&m->mtx);
- pqueue_enqueue(thread, queue);
return thread;
}
@@ -767,9 +888,8 @@ funcname_thread_add_timer_timeval (struct thread_master *m,
/* Add timer event thread. */
struct thread *
funcname_thread_add_timer (struct thread_master *m,
- int (*func) (struct thread *),
- void *arg, long timer,
- debugargdef)
+ int (*func) (struct thread *), void *arg, long timer,
+ struct thread **t_ptr, debugargdef)
{
struct timeval trel;
@@ -778,16 +898,15 @@ funcname_thread_add_timer (struct thread_master *m,
trel.tv_sec = timer;
trel.tv_usec = 0;
- return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg,
- &trel, debugargpass);
+ return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg, &trel,
+ t_ptr, debugargpass);
}
/* Add timer event thread with "millisecond" resolution */
struct thread *
funcname_thread_add_timer_msec (struct thread_master *m,
- int (*func) (struct thread *),
- void *arg, long timer,
- debugargdef)
+ int (*func) (struct thread *), void *arg, long timer,
+ struct thread **t_ptr, debugargdef)
{
struct timeval trel;
@@ -796,27 +915,25 @@ funcname_thread_add_timer_msec (struct thread_master *m,
trel.tv_sec = timer / 1000;
trel.tv_usec = 1000*(timer % 1000);
- return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER,
- arg, &trel, debugargpass);
+ return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg, &trel,
+ t_ptr, debugargpass);
}
/* Add timer event thread with "millisecond" resolution */
struct thread *
funcname_thread_add_timer_tv (struct thread_master *m,
- int (*func) (struct thread *),
- void *arg, struct timeval *tv,
- debugargdef)
+ int (*func) (struct thread *), void *arg, struct timeval *tv,
+ struct thread **t_ptr, debugargdef)
{
- return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER,
- arg, tv, debugargpass);
+ return funcname_thread_add_timer_timeval (m, func, THREAD_TIMER, arg, tv,
+ t_ptr, debugargpass);
}
/* Add a background thread, with an optional millisec delay */
struct thread *
funcname_thread_add_background (struct thread_master *m,
- int (*func) (struct thread *),
- void *arg, long delay,
- debugargdef)
+ int (*func) (struct thread *), void *arg, long delay,
+ struct thread **t_ptr, debugargdef)
{
struct timeval trel;
@@ -833,23 +950,43 @@ funcname_thread_add_background (struct thread_master *m,
trel.tv_usec = 0;
}
- return funcname_thread_add_timer_timeval (m, func, THREAD_BACKGROUND,
- arg, &trel, debugargpass);
+ return funcname_thread_add_timer_timeval (m, func, THREAD_BACKGROUND, arg, &trel,
+ t_ptr, debugargpass);
}
/* Add simple event thread. */
struct thread *
funcname_thread_add_event (struct thread_master *m,
- int (*func) (struct thread *), void *arg, int val,
- debugargdef)
+ int (*func) (struct thread *), void *arg, int val,
+ struct thread **t_ptr, debugargdef)
{
struct thread *thread;
assert (m != NULL);
- thread = thread_get (m, THREAD_EVENT, func, arg, debugargpass);
- thread->u.val = val;
- thread_list_add (&m->event, thread);
+ pthread_mutex_lock (&m->mtx);
+ {
+ if (t_ptr && *t_ptr) // thread is already scheduled; don't reschedule
+ {
+ pthread_mutex_unlock (&m->mtx);
+ return NULL;
+ }
+
+ thread = thread_get (m, THREAD_EVENT, func, arg, debugargpass);
+ pthread_mutex_lock (&thread->mtx);
+ {
+ thread->u.val = val;
+ thread_list_add (&m->event, thread);
+ }
+ pthread_mutex_unlock (&thread->mtx);
+
+ if (t_ptr)
+ {
+ *t_ptr = thread;
+ thread->ref = t_ptr;
+ }
+ }
+ pthread_mutex_unlock (&m->mtx);
return thread;
}
@@ -880,14 +1017,22 @@ thread_cancel_read_or_write (struct thread *thread, short int state)
fd_clear_read_write (thread);
}
-/* Cancel thread from scheduler. */
+/**
+ * Cancel thread from scheduler.
+ *
+ * This function is *NOT* MT-safe. DO NOT call it from any other pthread except
+ * the one which owns thread->master.
+ */
void
thread_cancel (struct thread *thread)
{
struct thread_list *list = NULL;
struct pqueue *queue = NULL;
struct thread **thread_array = NULL;
-
+
+ pthread_mutex_lock (&thread->master->mtx);
+ pthread_mutex_lock (&thread->mtx);
+
switch (thread->type)
{
case THREAD_READ:
@@ -919,15 +1064,14 @@ thread_cancel (struct thread *thread)
queue = thread->master->background;
break;
default:
- return;
+ goto done;
break;
}
if (queue)
{
assert(thread->index >= 0);
- assert(thread == queue->array[thread->index]);
- pqueue_remove_at(thread->index, queue);
+ pqueue_remove (thread, queue);
}
else if (list)
{
@@ -942,7 +1086,14 @@ thread_cancel (struct thread *thread)
assert(!"Thread should be either in queue or list or array!");
}
+ if (thread->ref)
+ *thread->ref = NULL;
+
thread_add_unuse (thread->master, thread);
+
+done:
+ pthread_mutex_unlock (&thread->mtx);
+ pthread_mutex_unlock (&thread->master->mtx);
}
/* Delete all events which has argument value arg. */
@@ -951,39 +1102,52 @@ thread_cancel_event (struct thread_master *m, void *arg)
{
unsigned int ret = 0;
struct thread *thread;
+ struct thread *t;
- thread = m->event.head;
- while (thread)
- {
- struct thread *t;
-
- t = thread;
- thread = t->next;
-
- if (t->arg == arg)
+ pthread_mutex_lock (&m->mtx);
+ {
+ thread = m->event.head;
+ while (thread)
+ {
+ t = thread;
+ pthread_mutex_lock (&t->mtx);
{
- ret++;
- thread_list_delete (&m->event, t);
- thread_add_unuse (m, t);
+ thread = t->next;
+
+ if (t->arg == arg)
+ {
+ ret++;
+ thread_list_delete (&m->event, t);
+ if (t->ref)
+ *t->ref = NULL;
+ thread_add_unuse (m, t);
+ }
}
- }
-
- /* thread can be on the ready list too */
- thread = m->ready.head;
- while (thread)
- {
- struct thread *t;
-
- t = thread;
- thread = t->next;
+ pthread_mutex_unlock (&t->mtx);
+ }
- if (t->arg == arg)
+ /* thread can be on the ready list too */
+ thread = m->ready.head;
+ while (thread)
+ {
+ t = thread;
+ pthread_mutex_lock (&t->mtx);
{
- ret++;
- thread_list_delete (&m->ready, t);
- thread_add_unuse (m, t);
+ thread = t->next;
+
+ if (t->arg == arg)
+ {
+ ret++;
+ thread_list_delete (&m->ready, t);
+ if (t->ref)
+ *t->ref = NULL;
+ thread_add_unuse (m, t);
+ }
}
- }
+ pthread_mutex_unlock (&t->mtx);
+ }
+ }
+ pthread_mutex_unlock (&m->mtx);
return ret;
}
@@ -1142,18 +1306,26 @@ thread_fetch (struct thread_master *m, struct thread *fetch)
struct timeval *timer_wait = &timer_val;
struct timeval *timer_wait_bg;
- while (1)
+ do
{
int num = 0;
/* Signals pre-empt everything */
- quagga_sigevent_process ();
+ if (m->handle_signals)
+ quagga_sigevent_process ();
+ pthread_mutex_lock (&m->mtx);
/* Drain the ready queue of already scheduled jobs, before scheduling
* more.
*/
if ((thread = thread_trim_head (&m->ready)) != NULL)
- return thread_run (m, thread, fetch);
+ {
+ fetch = thread_run (m, thread, fetch);
+ if (fetch->ref)
+ *fetch->ref = NULL;
+ pthread_mutex_unlock (&m->mtx);
+ return fetch;
+ }
/* To be fair to all kinds of threads, and avoid starvation, we
* need to be careful to consider all thread types for scheduling
@@ -1193,8 +1365,12 @@ thread_fetch (struct thread_master *m, struct thread *fetch)
if (num < 0)
{
if (errno == EINTR)
- continue; /* signal received - process it */
+ {
+ pthread_mutex_unlock (&m->mtx);
+ continue; /* signal received - process it */
+ }
zlog_warn ("select() error: %s", safe_strerror (errno));
+ pthread_mutex_unlock (&m->mtx);
return NULL;
}
@@ -1214,15 +1390,32 @@ thread_fetch (struct thread_master *m, struct thread *fetch)
list at this time. If this is code is uncommented, then background
timer threads will not run unless there is nothing else to do. */
if ((thread = thread_trim_head (&m->ready)) != NULL)
- return thread_run (m, thread, fetch);
+ {
+ fetch = thread_run (m, thread, fetch);
+ if (fetch->ref)
+ *fetch->ref = NULL;
+ pthread_mutex_unlock (&m->mtx);
+ return fetch;
+ }
#endif
/* Background timer/events, lowest priority */
thread_timer_process (m->background, &now);
if ((thread = thread_trim_head (&m->ready)) != NULL)
- return thread_run (m, thread, fetch);
- }
+ {
+ fetch = thread_run (m, thread, fetch);
+ if (fetch->ref)
+ *fetch->ref = NULL;
+ pthread_mutex_unlock (&m->mtx);
+ return fetch;
+ }
+
+ pthread_mutex_unlock (&m->mtx);
+
+ } while (m->spin);
+
+ return NULL;
}
unsigned long
@@ -1247,13 +1440,23 @@ thread_consumed_time (RUSAGE_T *now, RUSAGE_T *start, unsigned long *cputime)
int
thread_should_yield (struct thread *thread)
{
- return monotime_since(&thread->real, NULL) > (int64_t)thread->yield;
+ int result;
+ pthread_mutex_lock (&thread->mtx);
+ {
+ result = monotime_since(&thread->real, NULL) > (int64_t)thread->yield;
+ }
+ pthread_mutex_unlock (&thread->mtx);
+ return result;
}
void
thread_set_yield_time (struct thread *thread, unsigned long yield_time)
{
- thread->yield = yield_time;
+ pthread_mutex_lock (&thread->mtx);
+ {
+ thread->yield = yield_time;
+ }
+ pthread_mutex_unlock (&thread->mtx);
}
void
@@ -1311,7 +1514,7 @@ thread_call (struct thread *thread)
}
/* Execute thread */
-struct thread *
+void
funcname_thread_execute (struct thread_master *m,
int (*func)(struct thread *),
void *arg,
@@ -1323,6 +1526,7 @@ funcname_thread_execute (struct thread_master *m,
memset (&dummy, 0, sizeof (struct thread));
+ pthread_mutex_init (&dummy.mtx, NULL);
dummy.type = THREAD_EVENT;
dummy.add_type = THREAD_EXECUTE;
dummy.master = NULL;
@@ -1331,13 +1535,15 @@ funcname_thread_execute (struct thread_master *m,
tmp.func = dummy.func = func;
tmp.funcname = dummy.funcname = funcname;
- dummy.hist = hash_get (cpu_record, &tmp,
- (void * (*) (void *))cpu_record_hash_alloc);
+ pthread_mutex_lock (&cpu_record_mtx);
+ {
+ dummy.hist = hash_get (cpu_record, &tmp,
+ (void * (*) (void *))cpu_record_hash_alloc);
+ }
+ pthread_mutex_unlock (&cpu_record_mtx);
dummy.schedfrom = schedfrom;
dummy.schedfrom_line = fromln;
thread_call (&dummy);
-
- return NULL;
}
diff --git a/lib/thread.h b/lib/thread.h
index 6cb7896e7d..218672c7bf 100644
--- a/lib/thread.h
+++ b/lib/thread.h
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_THREAD_H
@@ -24,6 +23,7 @@
#include <zebra.h>
#include "monotime.h"
+#include <pthread.h>
struct rusage_t
{
@@ -84,6 +84,10 @@ struct thread_master
int fd_limit;
struct fd_handler handler;
unsigned long alloc;
+ long selectpoll_timeout;
+ bool spin;
+ bool handle_signals;
+ pthread_mutex_t mtx;
};
typedef unsigned char thread_type;
@@ -91,25 +95,27 @@ typedef unsigned char thread_type;
/* Thread itself. */
struct thread
{
- thread_type type; /* thread type */
- thread_type add_type; /* thread type */
- struct thread *next; /* next pointer of the thread */
- struct thread *prev; /* previous pointer of the thread */
- struct thread_master *master; /* pointer to the struct thread_master. */
- int (*func) (struct thread *); /* event function */
- void *arg; /* event argument */
+ thread_type type; /* thread type */
+ thread_type add_type; /* thread type */
+ struct thread *next; /* next pointer of the thread */
+ struct thread *prev; /* previous pointer of the thread */
+ struct thread **ref; /* external reference (if given) */
+ struct thread_master *master; /* pointer to the struct thread_master */
+ int (*func) (struct thread *); /* event function */
+ void *arg; /* event argument */
union {
- int val; /* second argument of the event. */
- int fd; /* file descriptor in case of read/write. */
- struct timeval sands; /* rest of time sands value. */
+ int val; /* second argument of the event. */
+ int fd; /* file descriptor in case of r/w */
+ struct timeval sands; /* rest of time sands value. */
} u;
- int index; /* used for timers to store position in queue */
+ int index; /* queue position for timers */
struct timeval real;
- struct cpu_thread_history *hist; /* cache pointer to cpu_history */
- unsigned long yield; /* yield time in us */
- const char *funcname;
- const char *schedfrom;
- int schedfrom_line;
+ struct cpu_thread_history *hist; /* cache pointer to cpu_history */
+ unsigned long yield; /* yield time in microseconds */
+ const char *funcname; /* name of thread function */
+ const char *schedfrom; /* source file thread was scheduled from */
+ int schedfrom_line; /* line number of source file */
+ pthread_mutex_t mtx; /* mutex for thread.c functions */
};
struct cpu_thread_history
@@ -147,30 +153,6 @@ struct cpu_thread_history
#define THREAD_FD(X) ((X)->u.fd)
#define THREAD_VAL(X) ((X)->u.val)
-#define THREAD_READ_ON(master,thread,func,arg,sock) \
- do { \
- if (! thread) \
- thread = thread_add_read (master, func, arg, sock); \
- } while (0)
-
-#define THREAD_WRITE_ON(master,thread,func,arg,sock) \
- do { \
- if (! thread) \
- thread = thread_add_write (master, func, arg, sock); \
- } while (0)
-
-#define THREAD_TIMER_ON(master,thread,func,arg,time) \
- do { \
- if (! thread) \
- thread = thread_add_timer (master, func, arg, time); \
- } while (0)
-
-#define THREAD_TIMER_MSEC_ON(master,thread,func,arg,time) \
- do { \
- if (! thread) \
- thread = thread_add_timer_msec (master, func, arg, time); \
- } while (0)
-
#define THREAD_OFF(thread) \
do { \
if (thread) \
@@ -186,46 +168,42 @@ struct cpu_thread_history
#define debugargdef const char *funcname, const char *schedfrom, int fromln
-#define thread_add_read(m,f,a,v) funcname_thread_add_read_write(THREAD_READ,m,f,a,v,#f,__FILE__,__LINE__)
-#define thread_add_write(m,f,a,v) funcname_thread_add_read_write(THREAD_WRITE,m,f,a,v,#f,__FILE__,__LINE__)
-#define thread_add_timer(m,f,a,v) funcname_thread_add_timer(m,f,a,v,#f,__FILE__,__LINE__)
-#define thread_add_timer_msec(m,f,a,v) funcname_thread_add_timer_msec(m,f,a,v,#f,__FILE__,__LINE__)
-#define thread_add_timer_tv(m,f,a,v) funcname_thread_add_timer_tv(m,f,a,v,#f,__FILE__,__LINE__)
-#define thread_add_event(m,f,a,v) funcname_thread_add_event(m,f,a,v,#f,__FILE__,__LINE__)
+#define thread_add_read(m,f,a,v,t) funcname_thread_add_read_write(THREAD_READ,m,f,a,v,t,#f,__FILE__,__LINE__)
+#define thread_add_write(m,f,a,v,t) funcname_thread_add_read_write(THREAD_WRITE,m,f,a,v,t,#f,__FILE__,__LINE__)
+#define thread_add_timer(m,f,a,v,t) funcname_thread_add_timer(m,f,a,v,t,#f,__FILE__,__LINE__)
+#define thread_add_timer_msec(m,f,a,v,t) funcname_thread_add_timer_msec(m,f,a,v,t,#f,__FILE__,__LINE__)
+#define thread_add_timer_tv(m,f,a,v,t) funcname_thread_add_timer_tv(m,f,a,v,t,#f,__FILE__,__LINE__)
+#define thread_add_event(m,f,a,v,t) funcname_thread_add_event(m,f,a,v,t,#f,__FILE__,__LINE__)
#define thread_execute(m,f,a,v) funcname_thread_execute(m,f,a,v,#f,__FILE__,__LINE__)
/* The 4th arg to thread_add_background is the # of milliseconds to delay. */
-#define thread_add_background(m,f,a,v) funcname_thread_add_background(m,f,a,v,#f,__FILE__,__LINE__)
+#define thread_add_background(m,f,a,v,t) funcname_thread_add_background(m,f,a,v,t,#f,__FILE__,__LINE__)
/* Prototypes. */
extern struct thread_master *thread_master_create (void);
extern void thread_master_free (struct thread_master *);
extern void thread_master_free_unused(struct thread_master *);
-extern struct thread *funcname_thread_add_read_write (int dir, struct thread_master *,
- int (*)(struct thread *),
- void *, int, debugargdef);
-extern struct thread *funcname_thread_add_timer (struct thread_master *,
- int (*)(struct thread *),
- void *, long, debugargdef);
-extern struct thread *funcname_thread_add_timer_msec (struct thread_master *,
- int (*)(struct thread *),
- void *, long, debugargdef);
-extern struct thread *funcname_thread_add_timer_tv (struct thread_master *,
- int (*)(struct thread *),
- void *, struct timeval *,
- debugargdef);
-extern struct thread *funcname_thread_add_event (struct thread_master *,
- int (*)(struct thread *),
- void *, int, debugargdef);
-extern struct thread *funcname_thread_add_background (struct thread_master *,
- int (*func)(struct thread *),
- void *arg,
- long milliseconds_to_delay,
- debugargdef);
-extern struct thread *funcname_thread_execute (struct thread_master *,
- int (*)(struct thread *),
- void *, int, debugargdef);
+extern struct thread * funcname_thread_add_read_write (int dir, struct thread_master *,
+ int (*)(struct thread *), void *, int, struct thread **, debugargdef);
+
+extern struct thread * funcname_thread_add_timer (struct thread_master *,
+ int (*)(struct thread *), void *, long, struct thread **, debugargdef);
+
+extern struct thread * funcname_thread_add_timer_msec (struct thread_master *,
+ int (*)(struct thread *), void *, long, struct thread **, debugargdef);
+
+extern struct thread * funcname_thread_add_timer_tv (struct thread_master *,
+ int (*)(struct thread *), void *, struct timeval *, struct thread **, debugargdef);
+
+extern struct thread * funcname_thread_add_event (struct thread_master *,
+ int (*)(struct thread *), void *, int, struct thread **, debugargdef);
+
+extern struct thread * funcname_thread_add_background (struct thread_master *,
+ int (*)(struct thread *), void *, long, struct thread **, debugargdef);
+
+extern void funcname_thread_execute (struct thread_master *,
+ int (*)(struct thread *), void *, int, debugargdef);
#undef debugargdef
extern void thread_cancel (struct thread *);
diff --git a/lib/vector.c b/lib/vector.c
index e16fcf5315..110cd2915c 100644
--- a/lib/vector.c
+++ b/lib/vector.c
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
diff --git a/lib/vector.h b/lib/vector.h
index f57f28bbd0..ab1d1e6aac 100644
--- a/lib/vector.h
+++ b/lib/vector.h
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_VECTOR_H
diff --git a/lib/vrf.c b/lib/vrf.c
index ce57bb6e7a..c4e527db5b 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -14,16 +14,16 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
#include "if.h"
#include "vrf.h"
+#include "vrf_int.h"
#include "prefix.h"
#include "table.h"
#include "log.h"
@@ -237,33 +237,6 @@ vrf_disable (struct vrf *vrf)
(*vrf_master.vrf_disable_hook) (vrf);
}
-
-/* Add a VRF hook. Please add hooks before calling vrf_init(). */
-void
-vrf_add_hook (int type, int (*func)(struct vrf *))
-{
- if (debug_vrf)
- zlog_debug ("%s: Add Hook %d to function %p", __PRETTY_FUNCTION__,
- type, func);
-
- switch (type) {
- case VRF_NEW_HOOK:
- vrf_master.vrf_new_hook = func;
- break;
- case VRF_DELETE_HOOK:
- vrf_master.vrf_delete_hook = func;
- break;
- case VRF_ENABLE_HOOK:
- vrf_master.vrf_enable_hook = func;
- break;
- case VRF_DISABLE_HOOK:
- vrf_master.vrf_disable_hook = func;
- break;
- default:
- break;
- }
-}
-
vrf_id_t
vrf_name_to_id (const char *name)
{
@@ -309,24 +282,6 @@ vrf_iflist_get (vrf_id_t vrf_id)
return vrf->iflist;
}
-/* Create the interface list for the specified VRF, if needed. */
-void
-vrf_iflist_create (vrf_id_t vrf_id)
-{
- struct vrf * vrf = vrf_lookup_by_id (vrf_id);
- if (vrf && !vrf->iflist)
- if_init (&vrf->iflist);
-}
-
-/* Free the interface list of the specified VRF. */
-void
-vrf_iflist_terminate (vrf_id_t vrf_id)
-{
- struct vrf * vrf = vrf_lookup_by_id (vrf_id);
- if (vrf && vrf->iflist)
- if_terminate (&vrf->iflist);
-}
-
/*
* VRF bit-map
*/
@@ -424,13 +379,21 @@ vrf_bitmap_check (vrf_bitmap_t bmap, vrf_id_t vrf_id)
/* Initialize VRF module. */
void
-vrf_init (void)
+vrf_init (int (*create)(struct vrf *),
+ int (*enable)(struct vrf *),
+ int (*disable)(struct vrf *),
+ int (*delete)(struct vrf *))
{
struct vrf *default_vrf;
if (debug_vrf)
zlog_debug ("%s: Initializing VRF subsystem", __PRETTY_FUNCTION__);
+ vrf_master.vrf_new_hook = create;
+ vrf_master.vrf_enable_hook = enable;
+ vrf_master.vrf_disable_hook = disable;
+ vrf_master.vrf_delete_hook = delete;
+
/* The default VRF always exists. */
default_vrf = vrf_get (VRF_DEFAULT, VRF_DEFAULT_NAME);
if (!default_vrf)
diff --git a/lib/vrf.h b/lib/vrf.h
index f8bb07ef48..fe2b4842b0 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_VRF_H
@@ -57,15 +56,6 @@ enum {
#define VRF_CMD_HELP_STR "Specify the VRF\nThe VRF name\n"
#define VRF_ALL_CMD_HELP_STR "Specify the VRF\nAll VRFs\n"
-/*
- * VRF hooks
- */
-
-#define VRF_NEW_HOOK 0 /* a new VRF is just created */
-#define VRF_DELETE_HOOK 1 /* a VRF is to be deleted */
-#define VRF_ENABLE_HOOK 2 /* a VRF is ready to use */
-#define VRF_DISABLE_HOOK 3 /* a VRF is to be unusable */
-
struct vrf
{
RB_ENTRY(vrf) id_entry, name_entry;
@@ -98,21 +88,9 @@ DECLARE_QOBJ_TYPE(vrf)
extern struct vrf_id_head vrfs_by_id;
extern struct vrf_name_head vrfs_by_name;
-/*
- * Add a specific hook to VRF module.
- * @param1: hook type
- * @param2: the callback function
- * - param 1: the VRF ID
- * - param 2: the address of the user data pointer (the user data
- * can be stored in or freed from there)
- */
-extern void vrf_add_hook (int, int (*)(struct vrf *));
-
extern struct vrf *vrf_lookup_by_id (vrf_id_t);
extern struct vrf *vrf_lookup_by_name (const char *);
extern struct vrf *vrf_get (vrf_id_t, const char *);
-extern void vrf_delete (struct vrf *);
-extern int vrf_enable (struct vrf *);
extern vrf_id_t vrf_name_to_id (const char *);
#define VRF_GET_ID(V,NAME) \
@@ -148,10 +126,6 @@ extern void *vrf_info_lookup (vrf_id_t);
extern struct list *vrf_iflist (vrf_id_t);
/* Get the interface list of the specified VRF. Create one if not find. */
extern struct list *vrf_iflist_get (vrf_id_t);
-/* Create the interface list for the specified VRF, if needed. */
-extern void vrf_iflist_create (vrf_id_t vrf_id);
-/* Free the interface list of the specified VRF. */
-extern void vrf_iflist_terminate (vrf_id_t vrf_id);
/*
* VRF bit-map: maintaining flags, one bit per VRF ID
@@ -168,9 +142,31 @@ extern int vrf_bitmap_check (vrf_bitmap_t, vrf_id_t);
/*
* VRF initializer/destructor
+ *
+ * create -> Called back when a new VRF is created. This
+ * can be either through these 3 options:
+ * 1) CLI mentions a vrf before OS knows about it
+ * 2) OS calls zebra and we create the vrf from OS
+ * callback
+ * 3) zebra calls individual protocols to notify
+ * about the new vrf
+ *
+ * enable -> Called back when a VRF is actually usable from
+ * an OS perspective ( 2 and 3 above )
+ *
+ * disable -> Called back when a VRF is being deleted from
+ * the system ( 2 and 3 ) above
+ *
+ * delete -> Called back when a vrf is being deleted from
+ * the system ( 2 and 3 ) above.
+ */
+extern void vrf_init (int (*create)(struct vrf *),
+ int (*enable)(struct vrf *),
+ int (*disable)(struct vrf *),
+ int (*delete)(struct vrf *));
+/*
+ * Call vrf_terminate when the protocol is being shutdown
*/
-/* Please add hooks before calling vrf_init(). */
-extern void vrf_init (void);
extern void vrf_terminate (void);
extern void vrf_cmd_init (int (*writefunc)(struct vty *vty));
diff --git a/lib/vrf_int.h b/lib/vrf_int.h
new file mode 100644
index 0000000000..f0301b7670
--- /dev/null
+++ b/lib/vrf_int.h
@@ -0,0 +1,56 @@
+/*
+ * VRF Internal Header
+ * Copyright (C) 2017 Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * This file is part of FRR.
+ *
+ * FRR is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * FRR is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with FRR; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+#ifndef __LIB_VRF_PRIVATE_H__
+#define __LIB_VRF_PRIVATE_H__
+
+#include "vrf.h"
+
+/*
+ * These functions should only be called by:
+ * zebra/if_netlink.c -> The interface from OS into Zebra
+ * lib/zclient.c -> The interface from Zebra to each daemon
+ *
+ * Why you ask? Well because these are the turn on/off
+ * functions and the only place we can really turn a
+ * vrf on properly is in the call up from the os -> zebra
+ * and the pass through of this informatoin from zebra -> protocols
+ */
+
+/*
+ * vrf_enable
+ *
+ * Given a newly running vrf enable it to be used
+ * by interested routing protocols
+ */
+extern int vrf_enable (struct vrf *);
+
+/*
+ * vrf_delete
+ *
+ * Given a vrf that is being deleted, delete it
+ * from interested parties
+ */
+extern void vrf_delete (struct vrf *);
+
+#endif
+
diff --git a/lib/vty.c b/lib/vty.c
index 36755b1d95..51e56fc1ae 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
@@ -734,6 +733,7 @@ vty_end_config (struct vty *vty)
case ZEBRA_NODE:
case RIP_NODE:
case RIPNG_NODE:
+ case EIGRP_NODE:
case BGP_NODE:
case BGP_VPNV4_NODE:
case BGP_VPNV6_NODE:
@@ -745,9 +745,11 @@ vty_end_config (struct vty *vty)
case BGP_VNC_L2_GROUP_NODE:
case BGP_IPV4_NODE:
case BGP_IPV4M_NODE:
+ case BGP_IPV4L_NODE:
case BGP_IPV6_NODE:
case BGP_IPV6M_NODE:
case BGP_EVPN_NODE:
+ case BGP_IPV6L_NODE:
case RMAP_NODE:
case OSPF_NODE:
case OSPF6_NODE:
@@ -952,14 +954,14 @@ vty_complete_command (struct vty *vty)
vty_backward_pure_word (vty);
vty_insert_word_overwrite (vty, matched[0]);
vty_self_insert (vty, ' ');
- XFREE (MTYPE_TMP, matched[0]);
+ XFREE (MTYPE_COMPLETION, matched[0]);
break;
case CMD_COMPLETE_MATCH:
vty_prompt (vty);
vty_redraw_line (vty);
vty_backward_pure_word (vty);
vty_insert_word_overwrite (vty, matched[0]);
- XFREE (MTYPE_TMP, matched[0]);
+ XFREE (MTYPE_COMPLETION, matched[0]);
break;
case CMD_COMPLETE_LIST_MATCH:
for (i = 0; matched[i] != NULL; i++)
@@ -967,7 +969,7 @@ vty_complete_command (struct vty *vty)
if (i != 0 && ((i % 6) == 0))
vty_out (vty, "%s", VTY_NEWLINE);
vty_out (vty, "%-10s ", matched[i]);
- XFREE (MTYPE_TMP, matched[i]);
+ XFREE (MTYPE_COMPLETION, matched[i]);
}
vty_out (vty, "%s", VTY_NEWLINE);
@@ -1106,6 +1108,26 @@ vty_describe_command (struct vty *vty)
else
vty_describe_fold (vty, width, desc_width, token);
+ if (IS_VARYING_TOKEN(token->type))
+ {
+ const char *ref = vector_slot(vline, vector_active(vline) - 1);
+
+ vector varcomps = vector_init (VECTOR_MIN_SIZE);
+ cmd_variable_complete (token, ref, varcomps);
+
+ if (vector_active(varcomps) > 0)
+ {
+ vty_out(vty, " ");
+ for (size_t j = 0; j < vector_active (varcomps); j++)
+ {
+ char *item = vector_slot (varcomps, j);
+ vty_out(vty, " %s", item);
+ XFREE(MTYPE_COMPLETION, item);
+ }
+ vty_out(vty, "%s", VTY_NEWLINE);
+ }
+ vector_free(varcomps);
+ }
#if 0
vty_out (vty, " %-*s %s%s", width
desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
@@ -1161,6 +1183,7 @@ vty_stop_input (struct vty *vty)
case ZEBRA_NODE:
case RIP_NODE:
case RIPNG_NODE:
+ case EIGRP_NODE:
case BGP_NODE:
case RMAP_NODE:
case OSPF_NODE:
@@ -2609,41 +2632,44 @@ static struct thread_master *vty_master;
static void
vty_event (enum event event, int sock, struct vty *vty)
{
- struct thread *vty_serv_thread;
+ struct thread *vty_serv_thread = NULL;
switch (event)
{
case VTY_SERV:
- vty_serv_thread = thread_add_read (vty_master, vty_accept, vty, sock);
+ vty_serv_thread = thread_add_read(vty_master, vty_accept, vty, sock, NULL);
vector_set_index (Vvty_serv_thread, sock, vty_serv_thread);
break;
#ifdef VTYSH
case VTYSH_SERV:
- vty_serv_thread = thread_add_read (vty_master, vtysh_accept, vty, sock);
+ vty_serv_thread = thread_add_read(vty_master, vtysh_accept, vty, sock, NULL);
vector_set_index (Vvty_serv_thread, sock, vty_serv_thread);
break;
case VTYSH_READ:
- vty->t_read = thread_add_read (vty_master, vtysh_read, vty, sock);
+ vty->t_read = NULL;
+ thread_add_read(vty_master, vtysh_read, vty, sock, &vty->t_read);
break;
case VTYSH_WRITE:
- vty->t_write = thread_add_write (vty_master, vtysh_write, vty, sock);
+ vty->t_write = NULL;
+ thread_add_write(vty_master, vtysh_write, vty, sock, &vty->t_write);
break;
#endif /* VTYSH */
case VTY_READ:
- vty->t_read = thread_add_read (vty_master, vty_read, vty, sock);
+ vty->t_read = NULL;
+ thread_add_read(vty_master, vty_read, vty, sock, &vty->t_read);
/* Time out treatment. */
if (vty->v_timeout)
{
if (vty->t_timeout)
thread_cancel (vty->t_timeout);
- vty->t_timeout =
- thread_add_timer (vty_master, vty_timeout, vty, vty->v_timeout);
+ vty->t_timeout = NULL;
+ thread_add_timer(vty_master, vty_timeout, vty, vty->v_timeout,
+ &vty->t_timeout);
}
break;
case VTY_WRITE:
- if (! vty->t_write)
- vty->t_write = thread_add_write (vty_master, vty_flush, vty, sock);
+ thread_add_write(vty_master, vty_flush, vty, sock, &vty->t_write);
break;
case VTY_TIMEOUT_RESET:
if (vty->t_timeout)
@@ -2653,8 +2679,9 @@ vty_event (enum event event, int sock, struct vty *vty)
}
if (vty->v_timeout)
{
- vty->t_timeout =
- thread_add_timer (vty_master, vty_timeout, vty, vty->v_timeout);
+ vty->t_timeout = NULL;
+ thread_add_timer(vty_master, vty_timeout, vty, vty->v_timeout,
+ &vty->t_timeout);
}
break;
}
diff --git a/lib/vty.h b/lib/vty.h
index 0ac73d95be..77edc7173a 100644
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -1,22 +1,22 @@
/* Virtual terminal [aka TeletYpe] interface routine
- Copyright (C) 1997 Kunihiro Ishiguro
-
-This file is part of GNU Zebra.
-
-GNU Zebra is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-GNU Zebra is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Zebra; see the file COPYING. If not, write to the Free
-Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+ * Copyright (C) 1997 Kunihiro Ishiguro
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
#ifndef _ZEBRA_VTY_H
#define _ZEBRA_VTY_H
diff --git a/lib/wheel.c b/lib/wheel.c
index fe53dea299..f273a29262 100644
--- a/lib/wheel.c
+++ b/lib/wheel.c
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "zebra.h"
#include "linklist.h"
@@ -60,9 +59,8 @@ wheel_timer_thread (struct thread *t)
slots_to_skip++;
wheel->slots_to_skip = slots_to_skip;
- THREAD_TIMER_MSEC_ON (wheel->master, wheel->timer,
- wheel_timer_thread, wheel,
- wheel->nexttime * slots_to_skip);
+ thread_add_timer_msec(wheel->master, wheel_timer_thread, wheel,
+ wheel->nexttime * slots_to_skip, &wheel->timer);
return 0;
}
@@ -91,9 +89,8 @@ wheel_init (struct thread_master *master, int period, size_t slots,
for (i = 0; i < slots; i++)
wheel->wheel_slot_lists[i] = list_new ();
- THREAD_TIMER_MSEC_ON (wheel->master, wheel->timer,
- wheel_timer_thread, wheel,
- wheel->nexttime);
+ thread_add_timer_msec(wheel->master, wheel_timer_thread, wheel,
+ wheel->nexttime, &wheel->timer);
return wheel;
}
@@ -124,9 +121,8 @@ int
wheel_start (struct timer_wheel *wheel)
{
if (!wheel->timer)
- THREAD_TIMER_MSEC_ON (wheel->master, wheel->timer,
- wheel_timer_thread, wheel,
- wheel->nexttime);
+ thread_add_timer_msec(wheel->master, wheel_timer_thread, wheel,
+ wheel->nexttime, &wheel->timer);
return 0;
}
diff --git a/lib/wheel.h b/lib/wheel.h
index 79d21e124b..07be79bf26 100644
--- a/lib/wheel.h
+++ b/lib/wheel.h
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __WHEEL_H__
#define __WHEEL_H__
diff --git a/lib/workqueue.c b/lib/workqueue.c
index 51017b34ea..f992588399 100644
--- a/lib/workqueue.c
+++ b/lib/workqueue.c
@@ -15,10 +15,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Quagga; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
@@ -126,8 +125,9 @@ work_queue_schedule (struct work_queue *wq, unsigned int delay)
&& (wq->thread == NULL)
&& (listcount (wq->items) > 0) )
{
- wq->thread = thread_add_background (wq->master, work_queue_run,
- wq, delay);
+ wq->thread = NULL;
+ thread_add_background(wq->master, work_queue_run, wq, delay,
+ &wq->thread);
/* set thread yield time, if needed */
if (wq->thread && wq->spec.yield != THREAD_YIELD_TIME_SLOT)
thread_set_yield_time (wq->thread, wq->spec.yield);
diff --git a/lib/workqueue.h b/lib/workqueue.h
index 548f96d8b0..45f02afc63 100644
--- a/lib/workqueue.h
+++ b/lib/workqueue.h
@@ -15,10 +15,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Quagga; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _QUAGGA_WORK_QUEUE_H
diff --git a/lib/zassert.h b/lib/zassert.h
index bf0a851ba8..082ad67897 100644
--- a/lib/zassert.h
+++ b/lib/zassert.h
@@ -13,10 +13,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with Quagga; see the file COPYING. If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _QUAGGA_ASSERT_H
diff --git a/lib/zclient.c b/lib/zclient.c
index d2a5186315..9823bc8d99 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -14,10 +14,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- * MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
@@ -26,6 +25,8 @@
#include "stream.h"
#include "buffer.h"
#include "network.h"
+#include "vrf.h"
+#include "vrf_int.h"
#include "if.h"
#include "log.h"
#include "thread.h"
@@ -310,8 +311,9 @@ zclient_flush_data(struct thread *thread)
return zclient_failed(zclient);
break;
case BUFFER_PENDING:
- zclient->t_write = thread_add_write(zclient->master, zclient_flush_data,
- zclient, zclient->sock);
+ zclient->t_write = NULL;
+ thread_add_write(zclient->master, zclient_flush_data, zclient, zclient->sock,
+ &zclient->t_write);
break;
case BUFFER_EMPTY:
break;
@@ -336,8 +338,8 @@ zclient_send_message(struct zclient *zclient)
THREAD_OFF(zclient->t_write);
break;
case BUFFER_PENDING:
- THREAD_WRITE_ON(zclient->master, zclient->t_write,
- zclient_flush_data, zclient, zclient->sock);
+ thread_add_write(zclient->master, zclient_flush_data, zclient,
+ zclient->sock, &zclient->t_write);
break;
}
return 0;
@@ -733,6 +735,18 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p,
s = zclient->obuf;
stream_reset (s);
+ /* Some checks for labeled-unicast. The current expectation is that each
+ * nexthop is accompanied by a label in the case of labeled-unicast.
+ */
+ if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL) &&
+ CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP))
+ {
+ /* We expect prefixes installed with labels and the number to match
+ * the number of nexthops.
+ */
+ assert (api->label_num == api->nexthop_num);
+ }
+
zclient_create_header (s, cmd, api->vrf_id);
/* Put type and nexthop. */
@@ -749,7 +763,7 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p,
/* Nexthop, ifindex, distance and metric information. */
if (CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP))
- {
+ {
/* traditional 32-bit data units */
if (CHECK_FLAG (api->flags, ZEBRA_FLAG_BLACKHOLE))
{
@@ -765,6 +779,9 @@ zapi_ipv4_route (u_char cmd, struct zclient *zclient, struct prefix_ipv4 *p,
{
stream_putc (s, NEXTHOP_TYPE_IPV4);
stream_put_in_addr (s, api->nexthop[i]);
+ /* For labeled-unicast, each nexthop is followed by label. */
+ if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL))
+ stream_putl (s, api->label[i]);
}
for (i = 0; i < api->ifindex_num; i++)
{
@@ -800,6 +817,18 @@ zapi_ipv4_route_ipv6_nexthop (u_char cmd, struct zclient *zclient,
s = zclient->obuf;
stream_reset (s);
+ /* Some checks for labeled-unicast. The current expectation is that each
+ * nexthop is accompanied by a label in the case of labeled-unicast.
+ */
+ if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL) &&
+ CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP))
+ {
+ /* We expect prefixes installed with labels and the number to match
+ * the number of nexthops.
+ */
+ assert (api->label_num == api->nexthop_num);
+ }
+
zclient_create_header (s, cmd, api->vrf_id);
/* Put type and nexthop. */
@@ -831,6 +860,9 @@ zapi_ipv4_route_ipv6_nexthop (u_char cmd, struct zclient *zclient,
{
stream_putc (s, NEXTHOP_TYPE_IPV6);
stream_write (s, (u_char *)api->nexthop[i], 16);
+ /* For labeled-unicast, each nexthop is followed by label. */
+ if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL))
+ stream_putl (s, api->label[i]);
}
for (i = 0; i < api->ifindex_num; i++)
{
@@ -869,6 +901,18 @@ zapi_ipv6_route (u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p,
s = zclient->obuf;
stream_reset (s);
+ /* Some checks for labeled-unicast. The current expectation is that each
+ * nexthop is accompanied by a label in the case of labeled-unicast.
+ */
+ if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL) &&
+ CHECK_FLAG (api->message, ZAPI_MESSAGE_NEXTHOP))
+ {
+ /* We expect prefixes installed with labels and the number to match
+ * the number of nexthops.
+ */
+ assert (api->label_num == api->nexthop_num);
+ }
+
zclient_create_header (s, cmd, api->vrf_id);
/* Put type and nexthop. */
@@ -907,6 +951,9 @@ zapi_ipv6_route (u_char cmd, struct zclient *zclient, struct prefix_ipv6 *p,
{
stream_putc (s, NEXTHOP_TYPE_IPV6);
stream_write (s, (u_char *)api->nexthop[i], 16);
+ /* For labeled-unicast, each nexthop is followed by label. */
+ if (CHECK_FLAG (api->message, ZAPI_MESSAGE_LABEL))
+ stream_putl (s, api->label[i]);
}
for (i = 0; i < api->ifindex_num; i++)
{
@@ -1879,6 +1926,12 @@ zclient_read (struct thread *thread)
if (zclient->interface_link_params)
(*zclient->interface_link_params) (command, zclient, length);
break;
+ case ZEBRA_FEC_UPDATE:
+ if (zclient_debug)
+ zlog_debug("zclient rcvd fec update\n");
+ if (zclient->fec_update)
+ (*zclient->fec_update) (command, zclient, length);
+ break;
default:
break;
}
@@ -1961,22 +2014,20 @@ zclient_event (enum event event, struct zclient *zclient)
switch (event)
{
case ZCLIENT_SCHEDULE:
- if (! zclient->t_connect)
- zclient->t_connect =
- thread_add_event (zclient->master, zclient_connect, zclient, 0);
+ thread_add_event(zclient->master, zclient_connect, zclient, 0,
+ &zclient->t_connect);
break;
case ZCLIENT_CONNECT:
if (zclient_debug)
zlog_debug ("zclient connect failures: %d schedule interval is now %d",
zclient->fail, zclient->fail < 3 ? 10 : 60);
- if (! zclient->t_connect)
- zclient->t_connect =
- thread_add_timer (zclient->master, zclient_connect, zclient,
- zclient->fail < 3 ? 10 : 60);
+ thread_add_timer(zclient->master, zclient_connect, zclient,
+ zclient->fail < 3 ? 10 : 60, &zclient->t_connect);
break;
case ZCLIENT_READ:
- zclient->t_read =
- thread_add_read (zclient->master, zclient_read, zclient, zclient->sock);
+ zclient->t_read = NULL;
+ thread_add_read(zclient->master, zclient_read, zclient, zclient->sock,
+ &zclient->t_read);
break;
}
}
diff --git a/lib/zclient.h b/lib/zclient.h
index d3d0a202c5..847ac3b671 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -7,16 +7,15 @@
* under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
- *
+ *
* GNU Zebra is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING. If not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _ZEBRA_ZCLIENT_H
@@ -94,6 +93,9 @@ typedef enum {
ZEBRA_LABEL_MANAGER_CONNECT,
ZEBRA_GET_LABEL_CHUNK,
ZEBRA_RELEASE_LABEL_CHUNK,
+ ZEBRA_FEC_REGISTER,
+ ZEBRA_FEC_UNREGISTER,
+ ZEBRA_FEC_UPDATE,
} zebra_message_types_t;
struct redist_proto
@@ -164,6 +166,7 @@ struct zclient
int (*redistribute_route_ipv4_del) (int, struct zclient *, uint16_t, vrf_id_t);
int (*redistribute_route_ipv6_add) (int, struct zclient *, uint16_t, vrf_id_t);
int (*redistribute_route_ipv6_del) (int, struct zclient *, uint16_t, vrf_id_t);
+ int (*fec_update) (int, struct zclient *, uint16_t);
};
/* Zebra API message flag. */
@@ -174,6 +177,7 @@ struct zclient
#define ZAPI_MESSAGE_TAG 0x10
#define ZAPI_MESSAGE_MTU 0x20
#define ZAPI_MESSAGE_SRCPFX 0x40
+#define ZAPI_MESSAGE_LABEL 0x80
/* Zserv protocol message header */
struct zserv_header
@@ -206,6 +210,9 @@ struct zapi_ipv4
u_char ifindex_num;
ifindex_t *ifindex;
+ u_char label_num;
+ unsigned int *label;
+
u_char distance;
u_int32_t metric;
@@ -297,6 +304,9 @@ struct zapi_ipv6
u_char ifindex_num;
ifindex_t *ifindex;
+ u_char label_num;
+ unsigned int *label;
+
u_char distance;
u_int32_t metric;
diff --git a/lib/zebra.h b/lib/zebra.h
index 760264d752..0a61c433d9 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -1,22 +1,22 @@
/* Zebra common header.
- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Kunihiro Ishiguro
-
-This file is part of GNU Zebra.
-
-GNU Zebra is free software; you can redistribute it and/or modify it
-under the terms of the GNU General Public License as published by the
-Free Software Foundation; either version 2, or (at your option) any
-later version.
-
-GNU Zebra is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Zebra; see the file COPYING. If not, write to the Free
-Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+ * Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Kunihiro Ishiguro
+ *
+ * This file is part of GNU Zebra.
+ *
+ * GNU Zebra is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * GNU Zebra is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
#ifndef _ZEBRA_H
#define _ZEBRA_H
@@ -393,6 +393,9 @@ extern const char *zserv_command_string (unsigned int command);
#define ZEBRA_FLAG_SCOPE_LINK 0x100
#define ZEBRA_FLAG_FIB_OVERRIDE 0x200
+/* Zebra FEC flags. */
+#define ZEBRA_FEC_REGISTER_LABEL_INDEX 0x1
+
#ifndef INADDR_LOOPBACK
#define INADDR_LOOPBACK 0x7f000001 /* Internet address 127.0.0.1. */
#endif
@@ -401,8 +404,8 @@ extern const char *zserv_command_string (unsigned int command);
typedef enum {
AFI_IP = 1,
AFI_IP6 = 2,
- AFI_L2VPN = 4,
- AFI_MAX = 5
+ AFI_L2VPN = 3,
+ AFI_MAX = 4
} afi_t;
/* Subsequent Address Family Identifier. */
@@ -413,11 +416,13 @@ typedef enum {
#define SAFI_ENCAP 5
#define SAFI_RESERVED_5 5
#define SAFI_EVPN 6
-#define SAFI_MAX 7
+#define SAFI_LABELED_UNICAST 7
+#define SAFI_MAX 8
#define IANA_SAFI_RESERVED 0
#define IANA_SAFI_UNICAST 1
#define IANA_SAFI_MULTICAST 2
+#define IANA_SAFI_LABELED_UNICAST 4
#define IANA_SAFI_ENCAP 7
#define IANA_SAFI_MPLS_VPN 128
@@ -512,6 +517,8 @@ static inline safi_t safi_iana2int (safi_t safi)
return SAFI_ENCAP;
if (safi == IANA_SAFI_EVPN)
return SAFI_EVPN;
+ if (safi == IANA_SAFI_LABELED_UNICAST)
+ return SAFI_LABELED_UNICAST;
return SAFI_MAX;
}
@@ -527,6 +534,8 @@ static inline safi_t safi_int2iana (safi_t safi)
return IANA_SAFI_ENCAP;
if (safi == SAFI_EVPN)
return IANA_SAFI_EVPN;
+ if (safi == SAFI_LABELED_UNICAST)
+ return IANA_SAFI_LABELED_UNICAST;
return IANA_SAFI_RESERVED;
}