summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--Makefile.am42
-rw-r--r--bgpd/bgp_attr.c24
-rw-r--r--bgpd/bgp_community.c3
-rw-r--r--bgpd/bgp_ecommunity.c3
-rw-r--r--bgpd/bgp_lcommunity.c3
-rw-r--r--bgpd/bgp_vty.c56
-rw-r--r--grpc/subdir.am2
-rw-r--r--ldpd/neighbor.c10
-rw-r--r--ldpd/subdir.am1
-rw-r--r--lib/hook.h2
-rw-r--r--lib/subdir.am2
-rw-r--r--python/callgraph-dot.py476
-rw-r--r--python/makefile.py34
-rw-r--r--python/makevars.py60
-rw-r--r--qpb/subdir.am1
-rw-r--r--tests/topotests/ldp-topo1/r3/how_mpls_table.ref10
-rw-r--r--tests/topotests/ldp-topo1/r4/how_mpls_table.ref9
-rw-r--r--tools/frr-llvm-cg.c649
-rw-r--r--tools/subdir.am12
-rw-r--r--zebra/rib.h29
-rw-r--r--zebra/rt_netlink.c20
-rw-r--r--zebra/rt_socket.c21
-rw-r--r--zebra/rtadv.c4
-rw-r--r--zebra/rtadv.h4
-rw-r--r--zebra/zebra_dplane.c2
-rw-r--r--zebra/zebra_fpm.c80
-rw-r--r--zebra/zebra_fpm_netlink.c33
-rw-r--r--zebra/zebra_nhg.c15
-rw-r--r--zebra/zebra_rib.c33
-rw-r--r--zebra/zebra_rnh.c31
-rw-r--r--zebra/zebra_rnh.h14
-rw-r--r--zebra/zebra_router.c4
-rw-r--r--zebra/zebra_vrf.h6
-rw-r--r--zebra/zebra_vty.c15
35 files changed, 1496 insertions, 218 deletions
diff --git a/.gitignore b/.gitignore
index 4c8370375d..fbbb04b60c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,6 +55,10 @@
*.pb-c.c
*.pb.cc
*_clippy.c
+*.bc
+*.cg.json
+*.cg.dot
+*.cg.svg
### gcov outputs
diff --git a/Makefile.am b/Makefile.am
index 1e3311fa7b..a959fd9e5a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -89,9 +89,11 @@ clippy-only: Makefile lib/clippy config.h
#AUTODERP# endif
EXTRA_DIST =
+EXTRA_PROGRAMS =
BUILT_SOURCES =
CLEANFILES =
DISTCLEANFILES =
+SUFFIXES =
examplesdir = $(exampledir)
@@ -231,12 +233,48 @@ EXTRA_DIST += \
vrrpd/Makefile \
# end
-clean-local: clean-python
-.PHONY: clean-python
+AM_V_LLVM_BC = $(am__v_LLVM_BC_$(V))
+am__v_LLVM_BC_ = $(am__v_LLVM_BC_$(AM_DEFAULT_VERBOSITY))
+am__v_LLVM_BC_0 = @echo " LLVM.BC " $@;
+am__v_LLVM_BC_1 =
+
+AM_V_LLVM_LD = $(am__v_LLVM_LD_$(V))
+am__v_LLVM_LD_ = $(am__v_LLVM_LD_$(AM_DEFAULT_VERBOSITY))
+am__v_LLVM_LD_0 = @echo " LLVM.LD " $@;
+am__v_LLVM_LD_1 =
+
+SUFFIXES += .lo.bc .o.bc
+
+.o.o.bc:
+ $(AM_V_LLVM_BC)$(COMPILE) -emit-llvm -c -o $@ $(patsubst %.o,%.c,$<)
+.lo.lo.bc:
+ $(AM_V_LLVM_BC)$(COMPILE) -emit-llvm -c -o $@ $(patsubst %.lo,%.c,$<)
+
+%.cg.json: %.bc tools/frr-llvm-cg
+ tools/frr-llvm-cg -o $@ $<
+%.cg.dot: %.cg.json
+ $(PYTHON) $(top_srcdir)/python/callgraph-dot.py $< $@
+%.cg.svg: %.cg.dot
+ @echo if the following command fails, you need to install graphviz.
+ @echo also, the output is nondeterministic. run it multiple times and use the nicest output.
+ @echo tuning parameters may yield nicer looking graphs as well.
+ fdp -GK=0.7 -Gstart=42231337 -Gmaxiter=2000 -Elen=2 -Gnodesep=1.5 -Tsvg -o$@ $<
+# don't delete intermediaries
+.PRECIOUS: %.cg.json %.cg.dot
+
+# <lib>.la.bc, <lib>.a.bc and <daemon>.bc targets are generated by
+# python/makefile.py
+LLVM_LINK = llvm-link-$(llvm_version)
+
+clean-local: clean-python clean-llvm-bitcode
+.PHONY: clean-python clean-llvm-bitcode
clean-python:
find . -name __pycache__ -o -name .pytest_cache | xargs rm -rf
find . -name "*.pyc" -o -name "*_clippy.c" | xargs rm -f
+clean-llvm-bitcode:
+ find . -name "*.bc" -o -name "*.cg.json" -o -name "*.cg.dot" -o -name "*.cg.svg" | xargs rm -f
+
redistclean:
$(MAKE) distclean CONFIG_CLEAN_FILES="$(filter-out $(EXTRA_DIST), $(CONFIG_CLEAN_FILES))"
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index b7e2f45195..d8566fed9f 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -1405,9 +1405,10 @@ static int bgp_attr_aspath(struct bgp_attr_parser_args *args)
/* Codification of AS 0 Processing */
if (aspath_check_as_zero(attr->aspath)) {
- flog_err(EC_BGP_ATTR_MAL_AS_PATH,
- "Malformed AS path, contains BGP_AS_ZERO(0) from %s",
- peer->host);
+ flog_err(
+ EC_BGP_ATTR_MAL_AS_PATH,
+ "Malformed AS path, AS number is 0 in the path from %s",
+ peer->host);
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
0);
}
@@ -1485,9 +1486,10 @@ static int bgp_attr_as4_path(struct bgp_attr_parser_args *args,
/* Codification of AS 0 Processing */
if (aspath_check_as_zero(*as4_path)) {
- flog_err(EC_BGP_ATTR_MAL_AS_PATH,
- "Malformed AS4 path, contains BGP_AS_ZERO(0) from %s",
- peer->host);
+ flog_err(
+ EC_BGP_ATTR_MAL_AS_PATH,
+ "Malformed AS path, AS number is 0 in the path from %s",
+ peer->host);
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
0);
}
@@ -1667,13 +1669,10 @@ static int bgp_attr_aggregator(struct bgp_attr_parser_args *args)
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR);
/* Codification of AS 0 Processing */
- if (aggregator_as == BGP_AS_ZERO) {
+ if (aggregator_as == BGP_AS_ZERO)
flog_err(EC_BGP_ATTR_LEN,
"AGGREGATOR AS number is 0 for aspath: %s",
aspath_print(attr->aspath));
- return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
- args->total);
- }
return BGP_ATTR_PARSE_PROCEED;
}
@@ -1703,13 +1702,10 @@ bgp_attr_as4_aggregator(struct bgp_attr_parser_args *args,
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR);
/* Codification of AS 0 Processing */
- if (aggregator_as == BGP_AS_ZERO) {
+ if (aggregator_as == BGP_AS_ZERO)
flog_err(EC_BGP_ATTR_LEN,
"AS4_AGGREGATOR AS number is 0 for aspath: %s",
aspath_print(attr->aspath));
- return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
- 0);
- }
return BGP_ATTR_PARSE_PROCEED;
}
diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c
index 30de84c878..0d60fbf479 100644
--- a/bgpd/bgp_community.c
+++ b/bgpd/bgp_community.c
@@ -40,6 +40,9 @@ static struct community *community_new(void)
/* Free communities value. */
void community_free(struct community **com)
{
+ if (!(*com))
+ return;
+
XFREE(MTYPE_COMMUNITY_VAL, (*com)->val);
XFREE(MTYPE_COMMUNITY_STR, (*com)->str);
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index 062a6477fa..d13da74b04 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -59,6 +59,9 @@ void ecommunity_strfree(char **s)
/* Allocate ecommunities. */
void ecommunity_free(struct ecommunity **ecom)
{
+ if (!(*ecom))
+ return;
+
XFREE(MTYPE_ECOMMUNITY_VAL, (*ecom)->val);
XFREE(MTYPE_ECOMMUNITY_STR, (*ecom)->str);
XFREE(MTYPE_ECOMMUNITY, *ecom);
diff --git a/bgpd/bgp_lcommunity.c b/bgpd/bgp_lcommunity.c
index f47ae91663..5900fcf862 100644
--- a/bgpd/bgp_lcommunity.c
+++ b/bgpd/bgp_lcommunity.c
@@ -44,6 +44,9 @@ static struct lcommunity *lcommunity_new(void)
/* Allocate lcommunities. */
void lcommunity_free(struct lcommunity **lcom)
{
+ if (!(*lcom))
+ return;
+
XFREE(MTYPE_LCOMMUNITY_VAL, (*lcom)->val);
XFREE(MTYPE_LCOMMUNITY_STR, (*lcom)->str);
if ((*lcom)->json)
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 0f09369860..8266b76111 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -2987,8 +2987,7 @@ DEFUN (no_bgp_bestpath_med,
/* "bgp bestpath bandwidth" configuration. */
DEFPY (bgp_bestpath_bw,
bgp_bestpath_bw_cmd,
- "[no$no] bgp bestpath bandwidth [<ignore|skip-missing|default-weight-for-missing>$bw_cfg]",
- NO_STR
+ "bgp bestpath bandwidth <ignore|skip-missing|default-weight-for-missing>$bw_cfg",
"BGP specific commands\n"
"Change the default bestpath selection\n"
"Link Bandwidth attribute\n"
@@ -3000,22 +2999,18 @@ DEFPY (bgp_bestpath_bw,
afi_t afi;
safi_t safi;
- if (no) {
- bgp->lb_handling = BGP_LINK_BW_ECMP;
- } else {
- if (!bw_cfg) {
- vty_out(vty, "%% Bandwidth configuration must be specified\n");
- return CMD_ERR_INCOMPLETE;
- }
- if (!strcmp(bw_cfg, "ignore"))
- bgp->lb_handling = BGP_LINK_BW_IGNORE_BW;
- else if (!strcmp(bw_cfg, "skip-missing"))
- bgp->lb_handling = BGP_LINK_BW_SKIP_MISSING;
- else if (!strcmp(bw_cfg, "default-weight-for-missing"))
- bgp->lb_handling = BGP_LINK_BW_DEFWT_4_MISSING;
- else
- return CMD_ERR_NO_MATCH;
+ if (!bw_cfg) {
+ vty_out(vty, "%% Bandwidth configuration must be specified\n");
+ return CMD_ERR_INCOMPLETE;
}
+ if (!strcmp(bw_cfg, "ignore"))
+ bgp->lb_handling = BGP_LINK_BW_IGNORE_BW;
+ else if (!strcmp(bw_cfg, "skip-missing"))
+ bgp->lb_handling = BGP_LINK_BW_SKIP_MISSING;
+ else if (!strcmp(bw_cfg, "default-weight-for-missing"))
+ bgp->lb_handling = BGP_LINK_BW_DEFWT_4_MISSING;
+ else
+ return CMD_ERR_NO_MATCH;
/* This config is used in route install, so redo that. */
FOREACH_AFI_SAFI (afi, safi) {
@@ -3027,6 +3022,32 @@ DEFPY (bgp_bestpath_bw,
return CMD_SUCCESS;
}
+DEFPY (no_bgp_bestpath_bw,
+ no_bgp_bestpath_bw_cmd,
+ "no bgp bestpath bandwidth [<ignore|skip-missing|default-weight-for-missing>$bw_cfg]",
+ NO_STR
+ "BGP specific commands\n"
+ "Change the default bestpath selection\n"
+ "Link Bandwidth attribute\n"
+ "Ignore link bandwidth (i.e., do regular ECMP, not weighted)\n"
+ "Ignore paths without link bandwidth for ECMP (if other paths have it)\n"
+ "Assign a low default weight (value 1) to paths not having link bandwidth\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ afi_t afi;
+ safi_t safi;
+
+ bgp->lb_handling = BGP_LINK_BW_ECMP;
+
+ /* This config is used in route install, so redo that. */
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (!bgp_fibupd_safi(safi))
+ continue;
+ bgp_zebra_announce_table(bgp, afi, safi);
+ }
+ return CMD_SUCCESS;
+}
+
/* "no bgp default ipv4-unicast". */
DEFUN (no_bgp_default_ipv4_unicast,
no_bgp_default_ipv4_unicast_cmd,
@@ -15757,6 +15778,7 @@ void bgp_vty_init(void)
/* "bgp bestpath bandwidth" commands */
install_element(BGP_NODE, &bgp_bestpath_bw_cmd);
+ install_element(BGP_NODE, &no_bgp_bestpath_bw_cmd);
/* "no bgp default ipv4-unicast" commands. */
install_element(BGP_NODE, &no_bgp_default_ipv4_unicast_cmd);
diff --git a/grpc/subdir.am b/grpc/subdir.am
index 048e12a024..045848aee7 100644
--- a/grpc/subdir.am
+++ b/grpc/subdir.am
@@ -26,6 +26,8 @@ am__v_PROTOC_ = $(am__v_PROTOC_$(AM_DEFAULT_VERBOSITY))
am__v_PROTOC_0 = @echo " PROTOC" $@;
am__v_PROTOC_1 =
+SUFFIXES += .pb.h .pb.cc .grpc.pb.cc
+
.proto.pb.cc:
$(AM_V_PROTOC)$(PROTOC) -I$(top_srcdir) --cpp_out=$(top_srcdir) $(top_srcdir)/$^
.proto.grpc.pb.cc:
diff --git a/ldpd/neighbor.c b/ldpd/neighbor.c
index ae51490c07..1aa53151e6 100644
--- a/ldpd/neighbor.c
+++ b/ldpd/neighbor.c
@@ -619,6 +619,16 @@ nbr_establish_connection(struct nbr *nbr)
#endif
}
+ if (nbr->af == AF_INET) {
+ if (sock_set_ipv4_tos(nbr->fd, IPTOS_PREC_INTERNETCONTROL) == -1)
+ log_warn("%s: lsr-id %s, sock_set_ipv4_tos error",
+ __func__, inet_ntoa(nbr->id));
+ } else if (nbr->af == AF_INET6) {
+ if (sock_set_ipv6_dscp(nbr->fd, IPTOS_PREC_INTERNETCONTROL) == -1)
+ log_warn("%s: lsr-id %s, sock_set_ipv6_dscp error",
+ __func__, inet_ntoa(nbr->id));
+ }
+
addr2sa(nbr->af, &nbr->laddr, 0, &local_su);
addr2sa(nbr->af, &nbr->raddr, LDP_PORT, &remote_su);
if (nbr->af == AF_INET6 && nbr->raddr_scope)
diff --git a/ldpd/subdir.am b/ldpd/subdir.am
index 09936e5c28..0b38c37872 100644
--- a/ldpd/subdir.am
+++ b/ldpd/subdir.am
@@ -28,7 +28,6 @@ ldpd_libldp_a_SOURCES = \
ldpd/ldp_vty_conf.c \
ldpd/ldp_vty_exec.c \
ldpd/ldp_zebra.c \
- ldpd/ldpd.c \
ldpd/ldpe.c \
ldpd/log.c \
ldpd/logmsg.c \
diff --git a/lib/hook.h b/lib/hook.h
index 3823cebe6a..bef5351e90 100644
--- a/lib/hook.h
+++ b/lib/hook.h
@@ -145,7 +145,7 @@ extern void _hook_register(struct hook *hook, struct hookent *stackent,
*/
#define _hook_reg_svar(hook, funcptr, arg, has_arg, module, funcname, prio) \
do { \
- static struct hookent stack_hookent = { .ent_on_heap = 0, }; \
+ static struct hookent stack_hookent = {}; \
_hook_register(hook, &stack_hookent, funcptr, arg, has_arg, \
module, funcname, prio); \
} while (0)
diff --git a/lib/subdir.am b/lib/subdir.am
index 2f8cbe5d52..b2f3e7c5de 100644
--- a/lib/subdir.am
+++ b/lib/subdir.am
@@ -415,7 +415,7 @@ am__v_CLIPPY_1 =
CLIPPY_DEPS = $(CLIPPY) $(top_srcdir)/python/clidef.py
-SUFFIXES = _clippy.c .proto .pb-c.c .pb-c.h .pb.h .pb.cc .grpc.pb.cc
+SUFFIXES += _clippy.c
.c_clippy.c:
$(AM_V_CLIPPY) $(CLIPPY) $(top_srcdir)/python/clidef.py -o $@ $<
diff --git a/python/callgraph-dot.py b/python/callgraph-dot.py
new file mode 100644
index 0000000000..4faf1dae16
--- /dev/null
+++ b/python/callgraph-dot.py
@@ -0,0 +1,476 @@
+# callgraph json to graphviz generator for FRR
+#
+# Copyright (C) 2020 David Lamparter for NetDEF, Inc.
+#
+# 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
+
+import re
+import sys
+import json
+
+class FunctionNode(object):
+ funcs = {}
+
+ def __init__(self, name):
+ super().__init__()
+ FunctionNode.funcs[name] = self
+
+ self.name = name
+ self.out = []
+ self.inb = []
+ self.rank = None
+ self.defined = False
+ self.defs = []
+
+ def __repr__(self):
+ return '<"%s()" rank=%r>' % (self.name, self.rank)
+
+ def define(self, attrs):
+ self.defined = True
+ self.defs.append((attrs['filename'], attrs['line']))
+ return self
+
+ def add_call(self, called, attrs):
+ return CallEdge(self, called, attrs)
+
+ def calls(self):
+ for e in self.out:
+ yield e.o
+
+ def calld(self):
+ for e in self.inb:
+ yield e.i
+
+ def unlink(self, other):
+ self.out = list([edge for edge in self.out if edge.o != other])
+ other.inb = list([edge for edge in other.inb if edge.i != other])
+
+ @classmethod
+ def get(cls, name):
+ if name in cls.funcs:
+ return cls.funcs[name]
+ return FunctionNode(name)
+
+class CallEdge(object):
+ def __init__(self, i, o, attrs):
+ self.i = i
+ self.o = o
+ self.is_external = attrs['is_external']
+ self.attrs = attrs
+
+ i.out.append(self)
+ o.inb.append(self)
+
+ def __repr__(self):
+ return '<"%s()" -> "%s()">' % (self.i.name, self.o.name)
+
+def nameclean(n):
+ if '.' in n:
+ return n.split('.', 1)[0]
+ return n
+
+def calc_rank(queue, direction):
+ nextq = queue
+
+ if direction == 1:
+ aggr = max
+ elem = lambda x: x.calls()
+ else:
+ aggr = min
+ elem = lambda x: x.calld()
+
+ currank = direction
+ cont = True
+
+ while len(nextq) > 0 and cont:
+ queue = nextq
+ nextq = []
+
+ #sys.stderr.write('rank %d\n' % currank)
+
+ cont = False
+
+ for node in queue:
+ if not node.defined:
+ node.rank = 0
+ continue
+
+ rank = direction
+ for other in elem(node):
+ if other is node:
+ continue
+ if other.rank is None:
+ nextq.append(node)
+ break
+ rank = aggr(rank, other.rank + direction)
+ else:
+ cont = True
+ node.rank = rank
+
+ currank += direction
+
+ return nextq
+
+class Graph(dict):
+ class Subgraph(set):
+ def __init__(self):
+ super().__init__()
+
+ class NodeGroup(set):
+ def __init__(self, members):
+ super().__init__(members)
+
+ class Node(object):
+ def __init__(self, graph, fn):
+ super().__init__()
+ self._fn = fn
+ self._fns = [fn]
+ self._graph = graph
+ self._calls = set()
+ self._calld = set()
+ self._group = None
+
+ def __repr__(self):
+ return '<Graph.Node "%s()"/%d>' % (self._fn.name, len(self._fns))
+
+ def __hash__(self):
+ return hash(self._fn.name)
+
+ def _finalize(self):
+ for called in self._fn.calls():
+ if called.name == self._fn.name:
+ continue
+ if called.name in self._graph:
+ self._calls.add(self._graph[called.name])
+ self._graph[called.name]._calld.add(self)
+
+ def unlink(self, other):
+ self._calls.remove(other)
+ other._calld.remove(self)
+
+ @property
+ def name(self):
+ return self._fn.name
+
+ def calls(self):
+ return self._calls
+ def calld(self):
+ return self._calld
+
+ def group(self, members):
+ assert self in members
+
+ pregroups = []
+ for g in [m._group for m in members]:
+ if g is None:
+ continue
+ if g in pregroups:
+ continue
+
+ assert g <= members
+ pregroups.append(g)
+
+ if len(pregroups) == 0:
+ group = self._graph.NodeGroup(members)
+ self._graph._groups.append(group)
+ elif len(pregroups) == 1:
+ group = pregroups[0]
+ group |= members
+ else:
+ for g in pregroups:
+ self._graph._groups.remove(g)
+ group = self._graph.NodeGroup(members)
+ self._graph._groups.append(group)
+
+ for m in members:
+ m._group = group
+ return group
+
+ def merge(self, other):
+ self._fns.extend(other._fns)
+ self._calls = (self._calls | other._calls) - {self, other}
+ self._calld = (self._calld | other._calld) - {self, other}
+ for c in other._calls:
+ if c == self:
+ continue
+ c._calld.remove(other)
+ c._calld.add(self)
+ for c in other._calld:
+ if c == self:
+ continue
+ c._calls.remove(other)
+ c._calls.add(self)
+ del self._graph[other._fn.name]
+
+ def __init__(self, funcs):
+ super().__init__()
+ self._funcs = funcs
+ for fn in funcs:
+ self[fn.name] = self.Node(self, fn)
+ for node in self.values():
+ node._finalize()
+ self._groups = []
+
+ def automerge(self):
+ nodes = list(self.values())
+
+ while len(nodes):
+ node = nodes.pop(0)
+
+ candidates = {node}
+ evalset = set(node.calls())
+ prevevalset = None
+
+ while prevevalset != evalset:
+ prevevalset = evalset
+ evalset = set()
+
+ for evnode in prevevalset:
+ inbound = set(evnode.calld())
+ if inbound <= candidates:
+ candidates.add(evnode)
+ evalset |= set(evnode.calls()) - candidates
+ else:
+ evalset.add(evnode)
+
+ #if len(candidates) > 1:
+ # for candidate in candidates:
+ # if candidate != node:
+ # #node.merge(candidate)
+ # if candidate in nodes:
+ # nodes.remove(candidate)
+ node.group(candidates)
+
+ for candidate in candidates:
+ if candidate in nodes:
+ nodes.remove(candidate)
+
+ def calc_subgraphs(self):
+ nodes = list(self.values())
+ self._subgraphs = []
+ up = {}
+ down = {}
+
+ self._linear_nodes = []
+
+ while len(nodes):
+ sys.stderr.write('%d\n' % len(nodes))
+ node = nodes.pop(0)
+
+ down[node] = set()
+ queue = [node]
+ while len(queue):
+ now = queue.pop()
+ down[node].add(now)
+ for calls in now.calls():
+ if calls in down[node]:
+ continue
+ queue.append(calls)
+
+ up[node] = set()
+ queue = [node]
+ while len(queue):
+ now = queue.pop()
+ up[node].add(now)
+ for calld in now.calld():
+ if calld in up[node]:
+ continue
+ queue.append(calld)
+
+ common = up[node] & down[node]
+
+ if len(common) == 1:
+ self._linear_nodes.append(node)
+ else:
+ sg = self.Subgraph()
+ sg |= common
+ self._subgraphs.append(sg)
+ for n in common:
+ if n != node:
+ nodes.remove(n)
+
+ return self._subgraphs, self._linear_nodes
+
+
+with open(sys.argv[1], 'r') as fd:
+ data = json.load(fd)
+
+extra_info = {
+ # zebra - LSP WQ
+ ('lsp_processq_add', 'work_queue_add'): [
+ 'lsp_process',
+ 'lsp_processq_del',
+ 'lsp_processq_complete',
+ ],
+ # zebra - main WQ
+ ('mq_add_handler', 'work_queue_add'): [
+ 'meta_queue_process',
+ ],
+ ('meta_queue_process', 'work_queue_add'): [
+ 'meta_queue_process',
+ ],
+ # bgpd - label pool WQ
+ ('bgp_lp_get', 'work_queue_add'): [
+ 'lp_cbq_docallback',
+ ],
+ ('bgp_lp_event_chunk', 'work_queue_add'): [
+ 'lp_cbq_docallback',
+ ],
+ ('bgp_lp_event_zebra_up', 'work_queue_add'): [
+ 'lp_cbq_docallback',
+ ],
+ # bgpd - main WQ
+ ('bgp_process', 'work_queue_add'): [
+ 'bgp_process_wq',
+ 'bgp_processq_del',
+ ],
+ ('bgp_add_eoiu_mark', 'work_queue_add'): [
+ 'bgp_process_wq',
+ 'bgp_processq_del',
+ ],
+ # clear node WQ
+ ('bgp_clear_route_table', 'work_queue_add'): [
+ 'bgp_clear_route_node',
+ 'bgp_clear_node_queue_del',
+ 'bgp_clear_node_complete',
+ ],
+ # rfapi WQs
+ ('rfapi_close', 'work_queue_add'): [
+ 'rfapi_deferred_close_workfunc',
+ ],
+ ('rfapiRibUpdatePendingNode', 'work_queue_add'): [
+ 'rfapiRibDoQueuedCallback',
+ 'rfapiRibQueueItemDelete',
+ ],
+}
+
+
+for func, fdata in data['functions'].items():
+ func = nameclean(func)
+ fnode = FunctionNode.get(func).define(fdata)
+
+ for call in fdata['calls']:
+ if call.get('type') in [None, 'unnamed', 'thread_sched']:
+ if call.get('target') is None:
+ continue
+ tgt = nameclean(call['target'])
+ fnode.add_call(FunctionNode.get(tgt), call)
+ for fptr in call.get('funcptrs', []):
+ fnode.add_call(FunctionNode.get(nameclean(fptr)), call)
+ if tgt == 'work_queue_add':
+ if (func, tgt) not in extra_info:
+ sys.stderr.write('%s:%d:%s(): work_queue_add() not handled\n' % (
+ call['filename'], call['line'], func))
+ else:
+ attrs = dict(call)
+ attrs.update({'is_external': False, 'type': 'workqueue'})
+ for dst in extra_info[func, tgt]:
+ fnode.add_call(FunctionNode.get(dst), call)
+ elif call['type'] == 'install_element':
+ vty_node = FunctionNode.get('VTY_NODE_%d' % call['vty_node'])
+ vty_node.add_call(FunctionNode.get(nameclean(call['target'])), call)
+ elif call['type'] == 'hook':
+ # TODO: edges for hooks from data['hooks']
+ pass
+
+n = FunctionNode.funcs
+
+# fix some very low end functions cycling back very far to the top
+if 'peer_free' in n:
+ n['peer_free'].unlink(n['bgp_timer_set'])
+ n['peer_free'].unlink(n['bgp_addpath_set_peer_type'])
+if 'bgp_path_info_extra_free' in n:
+ n['bgp_path_info_extra_free'].rank = 0
+
+if 'zlog_ref' in n:
+ n['zlog_ref'].rank = 0
+if 'mt_checkalloc' in n:
+ n['mt_checkalloc'].rank = 0
+
+queue = list(FunctionNode.funcs.values())
+queue = calc_rank(queue, 1)
+queue = calc_rank(queue, -1)
+
+sys.stderr.write('%d functions in cyclic set\n' % len(queue))
+
+graph = Graph(queue)
+graph.automerge()
+
+gv_nodes = []
+gv_edges = []
+
+sys.stderr.write('%d groups after automerge\n' % len(graph._groups))
+
+def is_vnc(n):
+ return n.startswith('rfapi') or n.startswith('vnc') or ('_vnc_' in n)
+
+_vncstyle = ',fillcolor="#ffffcc",style=filled'
+cyclic_set_names = set([fn.name for fn in graph.values()])
+
+for i, group in enumerate(graph._groups):
+ if len(group) > 1:
+ group.num = i
+ gv_nodes.append('\tsubgraph cluster_%d {' % i)
+ gv_nodes.append('\t\tcolor=blue;')
+ for gn in group:
+ has_cycle_callers = set(gn.calld()) - group
+ has_ext_callers = set([edge.i.name for edge in gn._fn.inb]) - cyclic_set_names
+
+ style = ''
+ etext = ''
+ if is_vnc(gn.name):
+ style += _vncstyle
+ if has_cycle_callers:
+ style += ',color=blue,penwidth=3'
+ if has_ext_callers:
+ style += ',fillcolor="#ffeebb",style=filled'
+ etext += '<br/><font point-size="10">(%d other callers)</font>' % (len(has_ext_callers))
+
+ gv_nodes.append('\t\t"%s" [shape=box,label=<%s%s>%s];' % (gn.name, '<br/>'.join([fn.name for fn in gn._fns]), etext, style))
+ gv_nodes.append('\t}')
+ else:
+ for gn in group:
+ has_ext_callers = set([edge.i.name for edge in gn._fn.inb]) - cyclic_set_names
+
+ style = ''
+ etext = ''
+ if is_vnc(gn.name):
+ style += _vncstyle
+ if has_ext_callers:
+ style += ',fillcolor="#ffeebb",style=filled'
+ etext += '<br/><font point-size="10">(%d other callers)</font>' % (len(has_ext_callers))
+ gv_nodes.append('\t"%s" [shape=box,label=<%s%s>%s];' % (gn.name, '<br/>'.join([fn.name for fn in gn._fns]), etext, style))
+
+edges = set()
+for gn in graph.values():
+ for calls in gn.calls():
+ if gn._group == calls._group:
+ gv_edges.append('\t"%s" -> "%s" [color="#55aa55",style=dashed];' % (gn.name, calls.name))
+ else:
+ def xname(nn):
+ if len(nn._group) > 1:
+ return 'cluster_%d' % nn._group.num
+ else:
+ return nn.name
+ tup = xname(gn), calls.name
+ if tup[0] != tup[1] and tup not in edges:
+ gv_edges.append('\t"%s" -> "%s" [weight=0.0,w=0.0,color=blue];' % tup)
+ edges.add(tup)
+
+with open(sys.argv[2], 'w') as fd:
+ fd.write('''digraph {
+ node [fontsize=13,fontname="Fira Sans"];
+%s
+}''' % '\n'.join(gv_nodes + [''] + gv_edges))
diff --git a/python/makefile.py b/python/makefile.py
index 9af397d373..948d3f7391 100644
--- a/python/makefile.py
+++ b/python/makefile.py
@@ -11,6 +11,7 @@ import subprocess
import re
import argparse
from string import Template
+from makevars import MakeReVars
argp = argparse.ArgumentParser(description = 'FRR Makefile extensions')
argp.add_argument('--dev-build', action = 'store_const', const = True,
@@ -20,13 +21,9 @@ args = argp.parse_args()
with open('Makefile', 'r') as fd:
before = fd.read()
-nolinecont = before.replace('\\\n', '')
-m = re.search('^clippy_scan\s*=([^#]*)(?:#.*)?$', nolinecont, flags=re.MULTILINE)
-if m is None:
- sys.stderr.write('failed to parse Makefile.in\n')
- sys.exit(2)
+mv = MakeReVars(before)
-clippy_scan = m.group(1).strip().split()
+clippy_scan = mv['clippy_scan'].strip().split()
for clippy_file in clippy_scan:
assert clippy_file.endswith('.c')
@@ -57,6 +54,7 @@ ${target}: ${clippybase}_clippy.c
lines = before.splitlines()
autoderp = '#AUTODERP# '
out_lines = []
+bcdeps = []
make_rule_re = re.compile('^([^:\s]+):\s*([^:\s]+)\s*($|\n)')
while lines:
@@ -80,6 +78,12 @@ while lines:
out_lines.append(line)
continue
+ target, dep = m.group(1), m.group(2)
+
+ if target.endswith('.lo') or target.endswith('.o'):
+ if not dep.endswith('.h'):
+ bcdeps.append('%s.bc: %s' % (target, target))
+ bcdeps.append('\t$(AM_V_LLVM_BC)$(COMPILE) -emit-llvm -c -o $@ %s' % (dep))
if m.group(2) in clippy_scan:
out_lines.append(clippyauxdep.substitute(target=m.group(1), clippybase=m.group(2)[:-2]))
@@ -88,6 +92,24 @@ while lines:
out_lines.append('# clippy{\n# main clippy targets')
for clippy_file in clippy_scan:
out_lines.append(clippydep.substitute(clippybase = clippy_file[:-2]))
+
+out_lines.append('')
+out_lines.extend(bcdeps)
+out_lines.append('')
+bc_targets = []
+for varname in ['bin_PROGRAMS', 'sbin_PROGRAMS', 'lib_LTLIBRARIES', 'module_LTLIBRARIES', 'noinst_LIBRARIES']:
+ bc_targets.extend(mv[varname].strip().split())
+for target in bc_targets:
+ amtgt = target.replace('/', '_').replace('.', '_').replace('-', '_')
+ objs = mv[amtgt + '_OBJECTS'].strip().split()
+ objs = [obj + '.bc' for obj in objs]
+ deps = mv.get(amtgt + '_DEPENDENCIES', '').strip().split()
+ deps = [d + '.bc' for d in deps if d.endswith('.a')]
+ objs.extend(deps)
+ out_lines.append('%s.bc: %s' % (target, ' '.join(objs)))
+ out_lines.append('\t$(AM_V_LLVM_LD)$(LLVM_LINK) -o $@ $^')
+ out_lines.append('')
+
out_lines.append('# }clippy')
out_lines.append('')
diff --git a/python/makevars.py b/python/makevars.py
index e0e2031a0d..1a85fbd6f5 100644
--- a/python/makevars.py
+++ b/python/makevars.py
@@ -4,14 +4,33 @@
import os
import subprocess
+import re
-class MakeVars(object):
+class MakeVarsBase(object):
'''
- makevars['FOO_CFLAGS'] gets you "FOO_CFLAGS" from Makefile
+ common code between MakeVars and MakeReVars
'''
def __init__(self):
self._data = dict()
+ def __getitem__(self, k):
+ if k not in self._data:
+ self.getvars([k])
+ return self._data[k]
+
+ def get(self, k, defval = None):
+ if k not in self._data:
+ self.getvars([k])
+ return self._data.get(k) or defval
+
+class MakeVars(MakeVarsBase):
+ '''
+ makevars['FOO_CFLAGS'] gets you "FOO_CFLAGS" from Makefile
+
+ This variant works by invoking make as a subprocess, i.e. Makefile must
+ be valid and working. (This is sometimes a problem if depfiles have not
+ been generated.)
+ '''
def getvars(self, varlist):
'''
get a batch list of variables from make. faster than individual calls.
@@ -39,12 +58,33 @@ class MakeVars(object):
v = v[1:-1]
self._data[k] = v
- def __getitem__(self, k):
- if k not in self._data:
- self.getvars([k])
- return self._data[k]
+class MakeReVars(MakeVarsBase):
+ '''
+ makevars['FOO_CFLAGS'] gets you "FOO_CFLAGS" from Makefile
- def get(self, k, defval = None):
- if k not in self._data:
- self.getvars([k])
- return self._data[k] or defval
+ This variant works by regexing through Makefile. This means the Makefile
+ does not need to be fully working, but on the other hand it doesn't support
+ fancy complicated make expressions.
+ '''
+ var_re = re.compile(r'^([^=#\n\s]+)[ \t]*=[ \t]*([^#\n]*)(?:#.*)?$', flags=re.MULTILINE)
+ repl_re = re.compile(r'\$(?:([A-Za-z])|\(([^\)]+)\))')
+
+ def __init__(self, maketext):
+ super().__init__()
+ self._vars = dict(self.var_re.findall(maketext.replace('\\\n', '')))
+
+ def replacevar(self, match):
+ varname = match.group(1) or match.group(2)
+ return self._vars.get(varname, '')
+
+ def getvars(self, varlist):
+ for varname in varlist:
+ if varname not in self._vars:
+ continue
+
+ val, prevval = self._vars[varname], None
+ while val != prevval:
+ prevval = val
+ val = self.repl_re.sub(self.replacevar, val)
+
+ self._data[varname] = val
diff --git a/qpb/subdir.am b/qpb/subdir.am
index 1864ba7369..80f8f3aca9 100644
--- a/qpb/subdir.am
+++ b/qpb/subdir.am
@@ -29,6 +29,7 @@ CLEANFILES += \
# end
EXTRA_DIST += qpb/qpb.proto
+SUFFIXES += .proto .pb-c.c .pb-c.h
if HAVE_PROTOBUF
diff --git a/tests/topotests/ldp-topo1/r3/how_mpls_table.ref b/tests/topotests/ldp-topo1/r3/how_mpls_table.ref
deleted file mode 100644
index 18f7df0ee4..0000000000
--- a/tests/topotests/ldp-topo1/r3/how_mpls_table.ref
+++ /dev/null
@@ -1,10 +0,0 @@
- Inbound Outbound
- Label Type Nexthop Label
--------- ------- --------------- --------
- 16 LDP 10.0.2.2 3
- 16 LDP 10.0.3.2 3
- 17 LDP 10.0.2.2 3
- 17 LDP 10.0.3.2 3
- 18 LDP 10.0.2.2 17
- 18 LDP 10.0.3.2 17
- 19 LDP 10.0.2.4 3
diff --git a/tests/topotests/ldp-topo1/r4/how_mpls_table.ref b/tests/topotests/ldp-topo1/r4/how_mpls_table.ref
deleted file mode 100644
index 40efab8b5b..0000000000
--- a/tests/topotests/ldp-topo1/r4/how_mpls_table.ref
+++ /dev/null
@@ -1,9 +0,0 @@
- Inbound Outbound
- Label Type Nexthop Label
--------- ------- --------------- --------
- 16 LDP 10.0.2.2 17
- 17 LDP 10.0.2.2 3
- 18 LDP 10.0.2.3 3
- 19 LDP 10.0.2.2 3
- 20 LDP 10.0.2.3 3
- 20 LDP 10.0.2.2 3
diff --git a/tools/frr-llvm-cg.c b/tools/frr-llvm-cg.c
new file mode 100644
index 0000000000..84a756a376
--- /dev/null
+++ b/tools/frr-llvm-cg.c
@@ -0,0 +1,649 @@
+// This is free and unencumbered software released into the public domain.
+//
+// Anyone is free to copy, modify, publish, use, compile, sell, or
+// distribute this software, either in source code form or as a compiled
+// binary, for any purpose, commercial or non-commercial, and by any
+// means.
+//
+// In jurisdictions that recognize copyright laws, the author or authors
+// of this software dedicate any and all copyright interest in the
+// software to the public domain. We make this dedication for the benefit
+// of the public at large and to the detriment of our heirs and
+// successors. We intend this dedication to be an overt act of
+// relinquishment in perpetuity of all present and future rights to this
+// software under copyright law.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// For more information, please refer to <http://unlicense.org/>
+
+/* based on example code: https://github.com/sheredom/llvm_bc_parsing_example
+ * which came under the above (un-)license. does not depend on any FRR
+ * pieces, so no reason to change the license.
+ *
+ * please note that while included in the FRR sources, this tool is in no way
+ * supported or maintained by the FRR community. it is provided as a
+ * "convenience"; while it worked at some point (using LLVM 8 / 9), it may
+ * easily break with a future LLVM version or any other factors.
+ *
+ * 2020-05-04, David Lamparter
+ */
+
+#include <string.h>
+#include <strings.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+
+#include <llvm-c/BitReader.h>
+#include <llvm-c/BitWriter.h>
+#include <llvm-c/Core.h>
+
+#include <json-c/json.h>
+
+/* if you want to use this without the special FRRouting defines,
+ * remove the following #define
+ */
+#define FRR_SPECIFIC
+
+static void dbgloc_add(struct json_object *jsobj, LLVMValueRef obj)
+{
+ unsigned file_len = 0;
+ const char *file = LLVMGetDebugLocFilename(obj, &file_len);
+ unsigned line = LLVMGetDebugLocLine(obj);
+
+ if (!file)
+ file = "???", file_len = 3;
+ else if (file[0] == '.' && file[1] == '/')
+ file += 2, file_len -= 2;
+
+ json_object_object_add(jsobj, "filename",
+ json_object_new_string_len(file, file_len));
+ json_object_object_add(jsobj, "line", json_object_new_int64(line));
+}
+
+static struct json_object *js_get_or_make(struct json_object *parent,
+ const char *key,
+ struct json_object *(*maker)(void))
+{
+ struct json_object *ret;
+
+ ret = json_object_object_get(parent, key);
+ if (ret)
+ return ret;
+ ret = maker();
+ json_object_object_add(parent, key, ret);
+ return ret;
+}
+
+static bool details_fptr_vars = false;
+static bool details_fptr_consts = true;
+
+enum called_fn {
+ FN_GENERIC = 0,
+ FN_NONAME,
+ FN_INSTALL_ELEMENT,
+ FN_THREAD_ADD,
+};
+
+static void walk_const_fptrs(struct json_object *js_call, LLVMValueRef value,
+ const char *prefix, bool *hdr_written)
+{
+ LLVMTypeRef type;
+ LLVMValueKind kind;
+
+ if (LLVMIsAGlobalVariable(value)) {
+ type = LLVMGlobalGetValueType(value);
+ value = LLVMGetInitializer(value);
+ } else {
+ type = LLVMTypeOf(value);
+ }
+
+ if (LLVMIsAFunction(value)) {
+ struct json_object *js_fptrs;
+
+ js_fptrs = js_get_or_make(js_call, "funcptrs",
+ json_object_new_array);
+
+ size_t fn_len;
+ const char *fn_name = LLVMGetValueName2(value, &fn_len);
+
+ size_t curlen = json_object_array_length(js_fptrs);
+ struct json_object *jsobj;
+ const char *s;
+
+ for (size_t i = 0; i < curlen; i++) {
+ jsobj = json_object_array_get_idx(js_fptrs, i);
+ s = json_object_get_string(jsobj);
+
+ if (s && !strcmp(s, fn_name))
+ return;
+ }
+
+ if (details_fptr_consts && !*hdr_written) {
+ fprintf(stderr,
+ "%s: calls function pointer from constant or global data\n",
+ prefix);
+ *hdr_written = true;
+ }
+ if (details_fptr_consts)
+ fprintf(stderr, "%s- constant: %.*s()\n",
+ prefix, (int)fn_len, fn_name);
+
+ json_object_array_add(js_fptrs,
+ json_object_new_string_len(fn_name,
+ fn_len));
+ return;
+ }
+
+ kind = LLVMGetValueKind(value);
+
+ unsigned len;
+ char *dump;
+
+ switch (kind) {
+ case LLVMUndefValueValueKind:
+ case LLVMConstantAggregateZeroValueKind:
+ case LLVMConstantPointerNullValueKind:
+ /* null pointer / array - ignore */
+ break;
+
+ case LLVMConstantIntValueKind:
+ /* integer - ignore */
+ break;
+
+ case LLVMConstantStructValueKind:
+ len = LLVMCountStructElementTypes(type);
+ for (unsigned i = 0; i < len; i++)
+ walk_const_fptrs(js_call, LLVMGetOperand(value, i),
+ prefix, hdr_written);
+ break;
+
+ case LLVMConstantArrayValueKind:
+ len = LLVMGetArrayLength(type);
+ for (unsigned i = 0; i < len; i++)
+ walk_const_fptrs(js_call, LLVMGetOperand(value, i),
+ prefix, hdr_written);
+ return;
+
+ default:
+ /* to help the user / development */
+ if (!*hdr_written) {
+ fprintf(stderr,
+ "%s: calls function pointer from constant or global data\n",
+ prefix);
+ *hdr_written = true;
+ }
+ dump = LLVMPrintValueToString(value);
+ fprintf(stderr,
+ "%s- value could not be processed:\n"
+ "%s- [kind=%d] %s\n",
+ prefix, prefix, kind, dump);
+ LLVMDisposeMessage(dump);
+ return;
+ }
+ return;
+}
+
+#ifdef FRR_SPECIFIC
+static bool is_thread_sched(const char *name, size_t len)
+{
+#define thread_prefix "funcname_"
+ static const char *const names[] = {
+ thread_prefix "thread_add_read_write",
+ thread_prefix "thread_add_timer",
+ thread_prefix "thread_add_timer_msec",
+ thread_prefix "thread_add_timer_tv",
+ thread_prefix "thread_add_event",
+ thread_prefix "thread_execute",
+ };
+ size_t i;
+
+ for (i = 0; i < sizeof(names) / sizeof(names[0]); i++) {
+ if (strlen(names[i]) != len)
+ continue;
+ if (!memcmp(names[i], name, len))
+ return true;
+ }
+ return false;
+}
+#endif
+
+static void process_call(struct json_object *js_calls,
+ struct json_object *js_special,
+ LLVMValueRef instr,
+ LLVMValueRef function)
+{
+ struct json_object *js_call, *js_fptrs = NULL;
+
+ LLVMValueRef called = LLVMGetCalledValue(instr);
+
+ if (LLVMIsAConstantExpr(called)) {
+ LLVMOpcode opcode = LLVMGetConstOpcode(called);
+
+ if (opcode == LLVMBitCast) {
+ LLVMValueRef op0 = LLVMGetOperand(called, 0);
+
+ if (LLVMIsAFunction(op0))
+ called = op0;
+ }
+ }
+
+ size_t called_len = 0;
+ const char *called_name = LLVMGetValueName2(called, &called_len);
+ unsigned n_args = LLVMGetNumArgOperands(instr);
+
+ bool is_external = LLVMIsDeclaration(called);
+ enum called_fn called_type = FN_GENERIC;
+
+ js_call = json_object_new_object();
+ json_object_array_add(js_calls, js_call);
+ dbgloc_add(js_call, instr);
+ json_object_object_add(js_call, "is_external",
+ json_object_new_boolean(is_external));
+
+ if (!called_name || called_len == 0) {
+ called_type = FN_NONAME;
+ json_object_object_add(js_call, "type",
+ json_object_new_string("indirect"));
+
+ LLVMValueRef last = called;
+
+ size_t name_len = 0;
+ const char *name_c = LLVMGetValueName2(function, &name_len);
+
+#ifdef FRR_SPECIFIC
+ /* information for FRR hooks is dumped for the registration
+ * in _hook_typecheck; we can safely ignore the funcptr here
+ */
+ if (strncmp(name_c, "hook_call_", 10) == 0)
+ return;
+#endif
+
+ unsigned file_len = 0;
+ const char *file = LLVMGetDebugLocFilename(instr, &file_len);
+ unsigned line = LLVMGetDebugLocLine(instr);
+
+ char prefix[256];
+ snprintf(prefix, sizeof(prefix), "%.*s:%d:%.*s()",
+ (int)file_len, file, line, (int)name_len, name_c);
+
+ while (LLVMIsALoadInst(last) || LLVMIsAGetElementPtrInst(last))
+ /* skipping over details for GEP here, but meh. */
+ last = LLVMGetOperand(last, 0);
+
+ if (LLVMIsAAllocaInst(last)) {
+ /* "alloca" is just generically all variables on the
+ * stack, this does not refer to C alloca() calls
+ *
+ * looking at the control flow in the function can
+ * give better results here, it's just not implemented
+ * (yet?)
+ */
+ fprintf(stderr,
+ "%s: call to a function pointer variable\n",
+ prefix);
+
+ if (details_fptr_vars) {
+ char *dump = LLVMPrintValueToString(called);
+ printf("%s- %s\n", prefix, dump);
+ LLVMDisposeMessage(dump);
+ }
+
+ json_object_object_add(
+ js_call, "type",
+ json_object_new_string("stack_fptr"));
+ } else if (LLVMIsACallInst(last)) {
+ /* calling the a function pointer returned from
+ * another function.
+ */
+ struct json_object *js_indirect;
+
+ js_indirect = js_get_or_make(js_call, "return_of",
+ json_object_new_array);
+
+ process_call(js_indirect, js_special, last, function);
+ } else if (LLVMIsAConstant(last)) {
+ /* function pointer is a constant (includes loading
+ * from complicated constants like structs or arrays.)
+ */
+ bool hdr_written = false;
+ walk_const_fptrs(js_call, last, prefix, &hdr_written);
+ if (details_fptr_consts && !hdr_written)
+ fprintf(stderr,
+ "%s: calls function pointer from constant or global data, but no non-NULL function pointers found\n",
+ prefix);
+ } else {
+ char *dump = LLVMPrintValueToString(called);
+ printf("\t%s\n", dump);
+ LLVMDisposeMessage(dump);
+ }
+ return;
+#ifdef FRR_SPECIFIC
+ } else if (!strcmp(called_name, "install_element")) {
+ called_type = FN_INSTALL_ELEMENT;
+
+ LLVMValueRef param0 = LLVMGetOperand(instr, 0);
+ if (!LLVMIsAConstantInt(param0))
+ goto out_nonconst;
+
+ long long vty_node = LLVMConstIntGetSExtValue(param0);
+ json_object_object_add(js_call, "vty_node",
+ json_object_new_int64(vty_node));
+
+ LLVMValueRef param1 = LLVMGetOperand(instr, 1);
+ if (!LLVMIsAGlobalVariable(param1))
+ goto out_nonconst;
+
+ LLVMValueRef intlz = LLVMGetInitializer(param1);
+ assert(intlz && LLVMIsConstant(intlz));
+
+ LLVMValueKind intlzkind = LLVMGetValueKind(intlz);
+ assert(intlzkind == LLVMConstantStructValueKind);
+
+ LLVMValueRef funcptr = LLVMGetOperand(intlz, 4);
+ assert(LLVMIsAFunction(funcptr));
+
+ size_t target_len = 0;
+ const char *target;
+ target = LLVMGetValueName2(funcptr, &target_len);
+
+ json_object_object_add(
+ js_call, "type",
+ json_object_new_string("install_element"));
+ json_object_object_add(
+ js_call, "target",
+ json_object_new_string_len(target, target_len));
+ return;
+
+ out_nonconst:
+ json_object_object_add(
+ js_call, "target",
+ json_object_new_string("install_element"));
+ return;
+ } else if (is_thread_sched(called_name, called_len)) {
+ called_type = FN_THREAD_ADD;
+
+ json_object_object_add(js_call, "type",
+ json_object_new_string("thread_sched"));
+ json_object_object_add(
+ js_call, "subtype",
+ json_object_new_string_len(called_name, called_len));
+
+ LLVMValueRef fparam;
+ if (strstr(called_name, "_read_"))
+ fparam = LLVMGetOperand(instr, 2);
+ else
+ fparam = LLVMGetOperand(instr, 1);
+ assert(fparam);
+
+ size_t target_len = 0;
+ const char *target;
+ target = LLVMGetValueName2(fparam, &target_len);
+
+ json_object_object_add(js_call, "target",
+ !target_len ? NULL :
+ json_object_new_string_len(target, target_len));
+ if (!LLVMIsAFunction(fparam))
+ json_object_object_add(js_call, "target_unresolved",
+ json_object_new_boolean(true));
+ return;
+ } else if (!strncmp(called_name, "_hook_typecheck_",
+ strlen("_hook_typecheck_"))) {
+ struct json_object *js_hook, *js_this;
+ const char *hook_name;
+
+ hook_name = called_name + strlen("_hook_typecheck_");
+
+ json_object_object_add(js_call, "type",
+ json_object_new_string("hook"));
+
+ LLVMValueRef param0 = LLVMGetOperand(instr, 0);
+ if (!LLVMIsAFunction(param0))
+ return;
+
+ size_t target_len = 0;
+ const char *target;
+ target = LLVMGetValueName2(param0, &target_len);
+
+ js_hook = js_get_or_make(js_special, "hooks",
+ json_object_new_object);
+ js_hook = js_get_or_make(js_hook, hook_name,
+ json_object_new_array);
+
+ js_this = json_object_new_object();
+ json_object_array_add(js_hook, js_this);
+
+ dbgloc_add(js_this, instr);
+ json_object_object_add(
+ js_this, "target",
+ json_object_new_string_len(target, target_len));
+ return;
+
+ /* TODO (FRR specifics):
+ * - workqueues - not sure we can do much there
+ * - zclient->* ?
+ */
+#endif /* FRR_SPECIFIC */
+ } else {
+ json_object_object_add(
+ js_call, "target",
+ json_object_new_string_len(called_name, called_len));
+ }
+
+ for (unsigned argno = 0; argno < n_args; argno++) {
+ LLVMValueRef param = LLVMGetOperand(instr, argno);
+ size_t target_len;
+ const char *target_name;
+
+ if (LLVMIsAFunction(param)) {
+ js_fptrs = js_get_or_make(js_call, "funcptrs",
+ json_object_new_array);
+
+ target_name = LLVMGetValueName2(param, &target_len);
+
+ json_object_array_add(js_fptrs,
+ json_object_new_string_len(
+ target_name, target_len));
+ }
+ }
+}
+
+static void process_fn(struct json_object *funcs,
+ struct json_object *js_special,
+ LLVMValueRef function)
+{
+ struct json_object *js_func, *js_calls;
+
+ size_t name_len = 0;
+ const char *name_c = LLVMGetValueName2(function, &name_len);
+ char *name;
+
+ name = strndup(name_c, name_len);
+
+ js_func = json_object_object_get(funcs, name);
+ if (js_func) {
+ unsigned file_len = 0;
+ const char *file = LLVMGetDebugLocFilename(function, &file_len);
+ unsigned line = LLVMGetDebugLocLine(function);
+
+ fprintf(stderr, "%.*s:%d:%s(): duplicate definition!\n",
+ (int)file_len, file, line, name);
+ free(name);
+ return;
+ }
+
+ js_func = json_object_new_object();
+ json_object_object_add(funcs, name, js_func);
+ free(name);
+
+ js_calls = json_object_new_array();
+ json_object_object_add(js_func, "calls", js_calls);
+
+ dbgloc_add(js_func, function);
+
+ for (LLVMBasicBlockRef basicBlock = LLVMGetFirstBasicBlock(function);
+ basicBlock; basicBlock = LLVMGetNextBasicBlock(basicBlock)) {
+
+ for (LLVMValueRef instr = LLVMGetFirstInstruction(basicBlock);
+ instr; instr = LLVMGetNextInstruction(instr)) {
+
+ if (LLVMIsAIntrinsicInst(instr))
+ continue;
+
+ if (LLVMIsACallInst(instr) || LLVMIsAInvokeInst(instr))
+ process_call(js_calls, js_special, instr,
+ function);
+ }
+ }
+}
+
+static void help(int retcode)
+{
+ fprintf(stderr,
+ "FRR LLVM bitcode to callgraph analyzer\n"
+ "\n"
+ "usage: frr-llvm-cg [-q|-v] [-o <JSONOUTPUT>] BITCODEINPUT\n"
+ "\n"
+ "\t-o FILENAME\twrite JSON output to file instead of stdout\n"
+ "\t-v\t\tbe more verbose\n"
+ "\t-q\t\tbe quiet\n"
+ "\n"
+ "BITCODEINPUT must be a LLVM binary bitcode file (not text\n"
+ "representation.) Use - to read from stdin.\n"
+ "\n"
+ "Note it may be necessary to build this binary tool against\n"
+ "the specific LLVM version that created the bitcode file.\n");
+ exit(retcode);
+}
+
+int main(int argc, char **argv)
+{
+ int opt;
+ const char *out = NULL;
+ const char *inp = NULL;
+ char v_or_q = '\0';
+
+ while ((opt = getopt(argc, argv, "hvqo:")) != -1) {
+ switch (opt) {
+ case 'o':
+ if (out)
+ help(1);
+ out = optarg;
+ break;
+ case 'v':
+ if (v_or_q && v_or_q != 'v')
+ help(1);
+ details_fptr_vars = true;
+ details_fptr_consts = true;
+ v_or_q = 'v';
+ break;
+ case 'q':
+ if (v_or_q && v_or_q != 'q')
+ help(1);
+ details_fptr_vars = false;
+ details_fptr_consts = false;
+ v_or_q = 'q';
+ break;
+ case 'h':
+ help(0);
+ return 0;
+ default:
+ help(1);
+ }
+ }
+
+ if (optind != argc - 1)
+ help(1);
+
+ inp = argv[optind];
+
+ LLVMMemoryBufferRef memoryBuffer;
+ char *message;
+ int ret;
+
+ // check if we are to read our input file from stdin
+ if (!strcmp(inp, "-")) {
+ inp = "<stdin>";
+ ret = LLVMCreateMemoryBufferWithSTDIN(&memoryBuffer, &message);
+ } else {
+ ret = LLVMCreateMemoryBufferWithContentsOfFile(
+ inp, &memoryBuffer, &message);
+ }
+
+ if (ret) {
+ fprintf(stderr, "failed to open %s: %s\n", inp, message);
+ free(message);
+ return 1;
+ }
+
+ // now create our module using the memorybuffer
+ LLVMModuleRef module;
+ if (LLVMParseBitcode2(memoryBuffer, &module)) {
+ fprintf(stderr, "%s: invalid bitcode\n", inp);
+ LLVMDisposeMemoryBuffer(memoryBuffer);
+ return 1;
+ }
+
+ // done with the memory buffer now, so dispose of it
+ LLVMDisposeMemoryBuffer(memoryBuffer);
+
+ struct json_object *js_root, *js_funcs, *js_special;
+
+ js_root = json_object_new_object();
+ js_funcs = json_object_new_object();
+ json_object_object_add(js_root, "functions", js_funcs);
+ js_special = json_object_new_object();
+ json_object_object_add(js_root, "special", js_special);
+
+ // loop through all the functions in the module
+ for (LLVMValueRef function = LLVMGetFirstFunction(module); function;
+ function = LLVMGetNextFunction(function)) {
+ if (LLVMIsDeclaration(function))
+ continue;
+
+ process_fn(js_funcs, js_special, function);
+ }
+
+ if (out) {
+ char tmpout[strlen(out) + 5];
+
+ snprintf(tmpout, sizeof(tmpout), "%s.tmp", out);
+ ret = json_object_to_file_ext(tmpout, js_root,
+ JSON_C_TO_STRING_PRETTY |
+ JSON_C_TO_STRING_PRETTY_TAB |
+ JSON_C_TO_STRING_NOSLASHESCAPE);
+ if (ret < 0) {
+ fprintf(stderr, "could not write JSON to file\n");
+ return 1;
+ }
+ if (rename(tmpout, out)) {
+ fprintf(stderr, "could not rename JSON output: %s\n",
+ strerror(errno));
+ unlink(tmpout);
+ return 1;
+ }
+ } else {
+ ret = json_object_to_fd(1, js_root,
+ JSON_C_TO_STRING_PRETTY |
+ JSON_C_TO_STRING_PRETTY_TAB |
+ JSON_C_TO_STRING_NOSLASHESCAPE);
+ if (ret < 0) {
+ fprintf(stderr, "could not write JSON to stdout\n");
+ return 1;
+ }
+ }
+
+ LLVMDisposeModule(module);
+
+ return 0;
+}
diff --git a/tools/subdir.am b/tools/subdir.am
index c637db6eb1..723a87d100 100644
--- a/tools/subdir.am
+++ b/tools/subdir.am
@@ -8,6 +8,10 @@ noinst_PROGRAMS += \
tools/gen_yang_deviations \
# end
+EXTRA_PROGRAMS += \
+ tools/frr-llvm-cg \
+ # end
+
sbin_PROGRAMS += tools/ssd
sbin_SCRIPTS += \
tools/frr-reload \
@@ -31,6 +35,14 @@ tools_gen_yang_deviations_LDADD = lib/libfrr.la $(LIBYANG_LIBS)
tools_ssd_SOURCES = tools/start-stop-daemon.c
+# don't bother autoconf'ing these for a simple optional tool
+llvm_version = $(shell echo __clang_major__ | $(CC) -xc -P -E -)
+tools_frr_llvm_cg_CFLAGS = $(AM_CFLAGS) `llvm-config-$(llvm_version) --cflags`
+tools_frr_llvm_cg_LDFLAGS = `llvm-config-$(llvm_version) --ldflags --libs`
+tools_frr_llvm_cg_SOURCES = \
+ tools/frr-llvm-cg.c \
+ # end
+
EXTRA_DIST += \
tools/etc \
tools/frr-reload \
diff --git a/zebra/rib.h b/zebra/rib.h
index 3717a12814..1667f17909 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -41,7 +41,7 @@
extern "C" {
#endif
-typedef enum { RNH_NEXTHOP_TYPE, RNH_IMPORT_CHECK_TYPE } rnh_type_t;
+enum rnh_type { RNH_NEXTHOP_TYPE, RNH_IMPORT_CHECK_TYPE };
PREDECL_LIST(rnh_list)
@@ -58,7 +58,7 @@ struct rnh {
afi_t afi;
- rnh_type_t type;
+ enum rnh_type type;
uint32_t seqno;
@@ -276,7 +276,7 @@ struct rtadv {
* Structure that is hung off of a route_table that holds information about
* the table.
*/
-typedef struct rib_table_info_t_ {
+struct rib_table_info {
/*
* Back pointer to zebra_vrf.
@@ -284,14 +284,13 @@ typedef struct rib_table_info_t_ {
struct zebra_vrf *zvrf;
afi_t afi;
safi_t safi;
+};
-} rib_table_info_t;
-
-typedef enum {
+enum rib_tables_iter_state {
RIB_TABLES_ITER_S_INIT,
RIB_TABLES_ITER_S_ITERATING,
RIB_TABLES_ITER_S_DONE
-} rib_tables_iter_state_t;
+};
/*
* Structure that holds state for iterating over all tables in the
@@ -301,16 +300,16 @@ typedef struct rib_tables_iter_t_ {
vrf_id_t vrf_id;
int afi_safi_ix;
- rib_tables_iter_state_t state;
+ enum rib_tables_iter_state state;
} rib_tables_iter_t;
/* Events/reasons triggering a RIB update. */
-typedef enum {
+enum rib_update_event {
RIB_UPDATE_KERNEL,
RIB_UPDATE_RMAP_CHANGE,
RIB_UPDATE_OTHER,
RIB_UPDATE_MAX
-} rib_update_event_t;
+};
extern void route_entry_copy_nexthops(struct route_entry *re,
struct nexthop *nh);
@@ -374,10 +373,10 @@ extern struct route_entry *rib_match_ipv4_multicast(vrf_id_t vrf_id,
extern struct route_entry *rib_lookup_ipv4(struct prefix_ipv4 *p,
vrf_id_t vrf_id);
-extern void rib_update(rib_update_event_t event);
-extern void rib_update_vrf(vrf_id_t vrf_id, rib_update_event_t event);
+extern void rib_update(enum rib_update_event event);
+extern void rib_update_vrf(vrf_id_t vrf_id, enum rib_update_event event);
extern void rib_update_table(struct route_table *table,
- rib_update_event_t event);
+ enum rib_update_event event);
extern int rib_sweep_route(struct thread *t);
extern void rib_sweep_table(struct route_table *table);
extern void rib_close_table(struct route_table *table);
@@ -412,9 +411,9 @@ extern void zebra_rib_evaluate_rn_nexthops(struct route_node *rn, uint32_t seq);
/*
* rib_table_info
*/
-static inline rib_table_info_t *rib_table_info(struct route_table *table)
+static inline struct rib_table_info *rib_table_info(struct route_table *table)
{
- return (rib_table_info_t *)route_table_get_info(table);
+ return (struct rib_table_info *)route_table_get_info(table);
}
/*
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 882babec81..466e985494 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -90,6 +90,18 @@ struct gw_family_t {
static const char ipv4_ll_buf[16] = "169.254.0.1";
static struct in_addr ipv4_ll;
+/* Is this a ipv4 over ipv6 route? */
+static bool is_route_v4_over_v6(unsigned char rtm_family,
+ enum nexthop_types_t nexthop_type)
+{
+ if (rtm_family == AF_INET
+ && (nexthop_type == NEXTHOP_TYPE_IPV6
+ || nexthop_type == NEXTHOP_TYPE_IPV6_IFINDEX))
+ return true;
+
+ return false;
+}
+
/* Helper to control use of kernel-level nexthop ids */
static bool kernel_nexthops_supported(void)
{
@@ -1165,9 +1177,7 @@ static void _netlink_route_build_singlepath(const struct prefix *p,
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
rtmsg->rtm_flags |= RTNH_F_ONLINK;
- if (rtmsg->rtm_family == AF_INET
- && (nexthop->type == NEXTHOP_TYPE_IPV6
- || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) {
+ if (is_route_v4_over_v6(rtmsg->rtm_family, nexthop->type)) {
rtmsg->rtm_flags |= RTNH_F_ONLINK;
addattr_l(nlmsg, req_size, RTA_GATEWAY, &ipv4_ll, 4);
addattr32(nlmsg, req_size, RTA_OIF, nexthop->ifindex);
@@ -1342,9 +1352,7 @@ _netlink_route_build_multipath(const struct prefix *p, const char *routedesc,
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
rtnh->rtnh_flags |= RTNH_F_ONLINK;
- if (rtmsg->rtm_family == AF_INET
- && (nexthop->type == NEXTHOP_TYPE_IPV6
- || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)) {
+ if (is_route_v4_over_v6(rtmsg->rtm_family, nexthop->type)) {
bytelen = 4;
rtnh->rtnh_flags |= RTNH_F_ONLINK;
rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTA_GATEWAY, &ipv4_ll,
diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c
index 6909bcb137..64fd7fa491 100644
--- a/zebra/rt_socket.c
+++ b/zebra/rt_socket.c
@@ -180,6 +180,7 @@ static int kernel_rtm(int cmd, const struct prefix *p,
switch (p->family) {
case AF_INET: {
struct in_addr loopback;
+
loopback.s_addr = htonl(INADDR_LOOPBACK);
sin_gate.sin.sin_addr = loopback;
#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
@@ -187,11 +188,21 @@ static int kernel_rtm(int cmd, const struct prefix *p,
sizeof(struct sockaddr_in);
#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
gate = true;
- }
- break;
- case AF_INET6:
- zlog_warn("v6 blackhole routes have not been programmed yet");
- break;
+ } break;
+ case AF_INET6: {
+ struct in6_addr loopback;
+
+ inet_pton(AF_INET6, "::1", &loopback);
+
+ sin_gate.sin6.sin6_addr = loopback;
+ sin_gate.sin6.sin6_family = AF_INET6;
+
+#ifdef HAVE_STRUCTSOCKADDR_SA_LEN
+ sin_gate.sin6.sin6_len =
+ sizeof(struct sockaddr_in6);
+#endif /* HAVE_STRUCTSOCKADDR_SA_LEN */
+ gate = true;
+ } break;
}
}
diff --git a/zebra/rtadv.c b/zebra/rtadv.c
index 0fb3390410..013eb5819c 100644
--- a/zebra/rtadv.c
+++ b/zebra/rtadv.c
@@ -171,7 +171,7 @@ static int rtadv_recv_packet(struct zebra_vrf *zvrf, int sock, uint8_t *buf,
/* Send router advertisement packet. */
static void rtadv_send_packet(int sock, struct interface *ifp,
- ipv6_nd_suppress_ra_status stop)
+ enum ipv6_nd_suppress_ra_status stop)
{
struct msghdr msg;
struct iovec iov;
@@ -1003,7 +1003,7 @@ void rtadv_delete_prefix(struct zebra_if *zif, const struct prefix *p)
}
static void ipv6_nd_suppress_ra_set(struct interface *ifp,
- ipv6_nd_suppress_ra_status status)
+ enum ipv6_nd_suppress_ra_status status)
{
struct zebra_if *zif;
struct zebra_vrf *zvrf;
diff --git a/zebra/rtadv.h b/zebra/rtadv.h
index 68a5bbcdbe..d7a1ccfb29 100644
--- a/zebra/rtadv.h
+++ b/zebra/rtadv.h
@@ -147,10 +147,10 @@ enum ipv6_nd_prefix_source {
PREFIX_SRC_BOTH,
};
-typedef enum {
+enum ipv6_nd_suppress_ra_status {
RA_ENABLE = 0,
RA_SUPPRESS,
-} ipv6_nd_suppress_ra_status;
+};
extern void rtadv_init(struct zebra_vrf *zvrf);
extern void rtadv_vrf_terminate(struct zebra_vrf *zvrf);
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 143354b166..cc8cab1ff5 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -1530,7 +1530,7 @@ int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
{
int ret = EINVAL;
const struct route_table *table = NULL;
- const rib_table_info_t *info;
+ const struct rib_table_info *info;
const struct prefix *p, *src_p;
struct zebra_ns *zns;
struct zebra_vrf *zvrf;
diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c
index 8f97c8cf47..47b4965396 100644
--- a/zebra/zebra_fpm.c
+++ b/zebra/zebra_fpm.c
@@ -76,15 +76,15 @@ static void zfpm_iterate_rmac_table(struct hash_bucket *backet, void *args);
* Structure that holds state for iterating over all route_node
* structures that are candidates for being communicated to the FPM.
*/
-typedef struct zfpm_rnodes_iter_t_ {
+struct zfpm_rnodes_iter {
rib_tables_iter_t tables_iter;
route_table_iter_t iter;
-} zfpm_rnodes_iter_t;
+};
/*
* Statistics.
*/
-typedef struct zfpm_stats_t_ {
+struct zfpm_stats {
unsigned long connect_calls;
unsigned long connect_no_sock;
@@ -115,13 +115,12 @@ typedef struct zfpm_stats_t_ {
unsigned long t_conn_up_yields;
unsigned long t_conn_up_aborts;
unsigned long t_conn_up_finishes;
-
-} zfpm_stats_t;
+};
/*
* States for the FPM state machine.
*/
-typedef enum {
+enum zfpm_state {
/*
* In this state we are not yet ready to connect to the FPM. This
@@ -147,20 +146,21 @@ typedef enum {
*/
ZFPM_STATE_ESTABLISHED
-} zfpm_state_t;
+};
/*
* Message format to be used to communicate with the FPM.
*/
-typedef enum {
+enum zfpm_msg_format {
ZFPM_MSG_FORMAT_NONE,
ZFPM_MSG_FORMAT_NETLINK,
ZFPM_MSG_FORMAT_PROTOBUF,
-} zfpm_msg_format_e;
+};
+
/*
* Globals.
*/
-typedef struct zfpm_glob_t_ {
+struct zfpm_glob {
/*
* True if the FPM module has been enabled.
@@ -170,11 +170,11 @@ typedef struct zfpm_glob_t_ {
/*
* Message format to be used to communicate with the fpm.
*/
- zfpm_msg_format_e message_format;
+ enum zfpm_msg_format message_format;
struct thread_master *master;
- zfpm_state_t state;
+ enum zfpm_state state;
in_addr_t fpm_server;
/*
@@ -231,7 +231,7 @@ typedef struct zfpm_glob_t_ {
struct thread *t_conn_down;
struct {
- zfpm_rnodes_iter_t iter;
+ struct zfpm_rnodes_iter iter;
} t_conn_down_state;
/*
@@ -241,7 +241,7 @@ typedef struct zfpm_glob_t_ {
struct thread *t_conn_up;
struct {
- zfpm_rnodes_iter_t iter;
+ struct zfpm_rnodes_iter iter;
} t_conn_up_state;
unsigned long connect_calls;
@@ -251,18 +251,18 @@ typedef struct zfpm_glob_t_ {
* Stats from the start of the current statistics interval up to
* now. These are the counters we typically update in the code.
*/
- zfpm_stats_t stats;
+ struct zfpm_stats stats;
/*
* Statistics that were gathered in the last collection interval.
*/
- zfpm_stats_t last_ivl_stats;
+ struct zfpm_stats last_ivl_stats;
/*
* Cumulative stats from the last clear to the start of the current
* statistics interval.
*/
- zfpm_stats_t cumulative_stats;
+ struct zfpm_stats cumulative_stats;
/*
* Stats interval timer.
@@ -273,18 +273,17 @@ typedef struct zfpm_glob_t_ {
* If non-zero, the last time when statistics were cleared.
*/
time_t last_stats_clear_time;
+};
-} zfpm_glob_t;
-
-static zfpm_glob_t zfpm_glob_space;
-static zfpm_glob_t *zfpm_g = &zfpm_glob_space;
+static struct zfpm_glob zfpm_glob_space;
+static struct zfpm_glob *zfpm_g = &zfpm_glob_space;
static int zfpm_trigger_update(struct route_node *rn, const char *reason);
static int zfpm_read_cb(struct thread *thread);
static int zfpm_write_cb(struct thread *thread);
-static void zfpm_set_state(zfpm_state_t state, const char *reason);
+static void zfpm_set_state(enum zfpm_state state, const char *reason);
static void zfpm_start_connect_timer(const char *reason);
static void zfpm_start_stats_timer(void);
static void zfpm_mac_info_del(struct fpm_mac_info_t *fpm_mac);
@@ -300,7 +299,7 @@ static inline int zfpm_thread_should_yield(struct thread *t)
/*
* zfpm_state_to_str
*/
-static const char *zfpm_state_to_str(zfpm_state_t state)
+static const char *zfpm_state_to_str(enum zfpm_state state)
{
switch (state) {
@@ -343,7 +342,7 @@ static time_t zfpm_get_elapsed_time(time_t reference)
/*
* zfpm_rnodes_iter_init
*/
-static inline void zfpm_rnodes_iter_init(zfpm_rnodes_iter_t *iter)
+static inline void zfpm_rnodes_iter_init(struct zfpm_rnodes_iter *iter)
{
memset(iter, 0, sizeof(*iter));
rib_tables_iter_init(&iter->tables_iter);
@@ -360,7 +359,8 @@ static inline void zfpm_rnodes_iter_init(zfpm_rnodes_iter_t *iter)
/*
* zfpm_rnodes_iter_next
*/
-static inline struct route_node *zfpm_rnodes_iter_next(zfpm_rnodes_iter_t *iter)
+static inline struct route_node *
+zfpm_rnodes_iter_next(struct zfpm_rnodes_iter *iter)
{
struct route_node *rn;
struct route_table *table;
@@ -389,7 +389,7 @@ static inline struct route_node *zfpm_rnodes_iter_next(zfpm_rnodes_iter_t *iter)
/*
* zfpm_rnodes_iter_pause
*/
-static inline void zfpm_rnodes_iter_pause(zfpm_rnodes_iter_t *iter)
+static inline void zfpm_rnodes_iter_pause(struct zfpm_rnodes_iter *iter)
{
route_table_iter_pause(&iter->iter);
}
@@ -397,7 +397,7 @@ static inline void zfpm_rnodes_iter_pause(zfpm_rnodes_iter_t *iter)
/*
* zfpm_rnodes_iter_cleanup
*/
-static inline void zfpm_rnodes_iter_cleanup(zfpm_rnodes_iter_t *iter)
+static inline void zfpm_rnodes_iter_cleanup(struct zfpm_rnodes_iter *iter)
{
route_table_iter_cleanup(&iter->iter);
rib_tables_iter_cleanup(&iter->tables_iter);
@@ -408,7 +408,7 @@ static inline void zfpm_rnodes_iter_cleanup(zfpm_rnodes_iter_t *iter)
*
* Initialize a statistics block.
*/
-static inline void zfpm_stats_init(zfpm_stats_t *stats)
+static inline void zfpm_stats_init(struct zfpm_stats *stats)
{
memset(stats, 0, sizeof(*stats));
}
@@ -416,7 +416,7 @@ static inline void zfpm_stats_init(zfpm_stats_t *stats)
/*
* zfpm_stats_reset
*/
-static inline void zfpm_stats_reset(zfpm_stats_t *stats)
+static inline void zfpm_stats_reset(struct zfpm_stats *stats)
{
zfpm_stats_init(stats);
}
@@ -424,7 +424,8 @@ static inline void zfpm_stats_reset(zfpm_stats_t *stats)
/*
* zfpm_stats_copy
*/
-static inline void zfpm_stats_copy(const zfpm_stats_t *src, zfpm_stats_t *dest)
+static inline void zfpm_stats_copy(const struct zfpm_stats *src,
+ struct zfpm_stats *dest)
{
memcpy(dest, src, sizeof(*dest));
}
@@ -440,8 +441,9 @@ static inline void zfpm_stats_copy(const zfpm_stats_t *src, zfpm_stats_t *dest)
* structure is composed entirely of counters. This can easily be
* changed when necessary.
*/
-static void zfpm_stats_compose(const zfpm_stats_t *s1, const zfpm_stats_t *s2,
- zfpm_stats_t *result)
+static void zfpm_stats_compose(const struct zfpm_stats *s1,
+ const struct zfpm_stats *s2,
+ struct zfpm_stats *result)
{
const unsigned long *p1, *p2;
unsigned long *result_p;
@@ -451,7 +453,7 @@ static void zfpm_stats_compose(const zfpm_stats_t *s1, const zfpm_stats_t *s2,
p2 = (const unsigned long *)s2;
result_p = (unsigned long *)result;
- num_counters = (sizeof(zfpm_stats_t) / sizeof(unsigned long));
+ num_counters = (sizeof(struct zfpm_stats) / sizeof(unsigned long));
for (i = 0; i < num_counters; i++) {
result_p[i] = p1[i] + p2[i];
@@ -512,7 +514,7 @@ static inline void zfpm_connect_off(void)
static int zfpm_conn_up_thread_cb(struct thread *thread)
{
struct route_node *rnode;
- zfpm_rnodes_iter_t *iter;
+ struct zfpm_rnodes_iter *iter;
rib_dest_t *dest;
zfpm_g->t_conn_up = NULL;
@@ -626,7 +628,7 @@ static void zfpm_connect_check(void)
static int zfpm_conn_down_thread_cb(struct thread *thread)
{
struct route_node *rnode;
- zfpm_rnodes_iter_t *iter;
+ struct zfpm_rnodes_iter *iter;
rib_dest_t *dest;
struct fpm_mac_info_t *mac = NULL;
@@ -1308,9 +1310,9 @@ static int zfpm_connect_cb(struct thread *t)
*
* Move state machine into the given state.
*/
-static void zfpm_set_state(zfpm_state_t state, const char *reason)
+static void zfpm_set_state(enum zfpm_state state, const char *reason)
{
- zfpm_state_t cur_state = zfpm_g->state;
+ enum zfpm_state cur_state = zfpm_g->state;
if (!reason)
reason = "Unknown";
@@ -1649,7 +1651,7 @@ static void zfpm_iterate_rmac_table(struct hash_bucket *backet, void *args)
}
/*
- * zfpm_stats_timer_cb
+ * struct zfpm_statsimer_cb
*/
static int zfpm_stats_timer_cb(struct thread *t)
{
@@ -1714,7 +1716,7 @@ void zfpm_start_stats_timer(void)
*/
static void zfpm_show_stats(struct vty *vty)
{
- zfpm_stats_t total_stats;
+ struct zfpm_stats total_stats;
time_t elapsed;
vty_out(vty, "\n%-40s %10s Last %2d secs\n\n", "Counter", "Total",
diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c
index 00909df1db..c580fe40d5 100644
--- a/zebra/zebra_fpm_netlink.c
+++ b/zebra/zebra_fpm_netlink.c
@@ -143,13 +143,13 @@ struct fpm_nh_encap_info_t {
};
/*
- * netlink_nh_info_t
+ * netlink_nh_info
*
* Holds information about a single nexthop for netlink. These info
* structures are transient and may contain pointers into rib
* data structures for convenience.
*/
-typedef struct netlink_nh_info_t_ {
+struct netlink_nh_info {
uint32_t if_index;
union g_addr *gateway;
@@ -160,14 +160,14 @@ typedef struct netlink_nh_info_t_ {
int recursive;
enum nexthop_types_t type;
struct fpm_nh_encap_info_t encap_info;
-} netlink_nh_info_t;
+};
/*
- * netlink_route_info_t
+ * netlink_route_info
*
* A structure for holding information for a netlink route message.
*/
-typedef struct netlink_route_info_t_ {
+struct netlink_route_info {
uint16_t nlmsg_type;
uint8_t rtm_type;
uint32_t rtm_table;
@@ -180,9 +180,9 @@ typedef struct netlink_route_info_t_ {
/*
* Nexthop structures
*/
- netlink_nh_info_t nhs[MULTIPATH_NUM];
+ struct netlink_nh_info nhs[MULTIPATH_NUM];
union g_addr *pref_src;
-} netlink_route_info_t;
+};
/*
* netlink_route_info_add_nh
@@ -192,11 +192,11 @@ typedef struct netlink_route_info_t_ {
*
* Returns true if a nexthop was added, false otherwise.
*/
-static int netlink_route_info_add_nh(netlink_route_info_t *ri,
+static int netlink_route_info_add_nh(struct netlink_route_info *ri,
struct nexthop *nexthop,
struct route_entry *re)
{
- netlink_nh_info_t nhi;
+ struct netlink_nh_info nhi;
union g_addr *src;
zebra_l3vni_t *zl3vni = NULL;
@@ -275,7 +275,7 @@ static uint8_t netlink_proto_from_route_type(int type)
*
* Returns true on success and false on failure.
*/
-static int netlink_route_info_fill(netlink_route_info_t *ri, int cmd,
+static int netlink_route_info_fill(struct netlink_route_info *ri, int cmd,
rib_dest_t *dest, struct route_entry *re)
{
struct nexthop *nexthop;
@@ -353,13 +353,13 @@ static int netlink_route_info_fill(netlink_route_info_t *ri, int cmd,
* Returns the number of bytes written to the buffer. 0 or a negative
* value indicates an error.
*/
-static int netlink_route_info_encode(netlink_route_info_t *ri, char *in_buf,
- size_t in_buf_len)
+static int netlink_route_info_encode(struct netlink_route_info *ri,
+ char *in_buf, size_t in_buf_len)
{
size_t bytelen;
unsigned int nexthop_num = 0;
size_t buf_offset;
- netlink_nh_info_t *nhi;
+ struct netlink_nh_info *nhi;
enum fpm_nh_encap_type_t encap;
struct rtattr *nest;
struct vxlan_encap_info_t *vxlan;
@@ -520,9 +520,10 @@ done:
*
* Helper function to log the information in a route_info structure.
*/
-static void zfpm_log_route_info(netlink_route_info_t *ri, const char *label)
+static void zfpm_log_route_info(struct netlink_route_info *ri,
+ const char *label)
{
- netlink_nh_info_t *nhi;
+ struct netlink_nh_info *nhi;
unsigned int i;
zfpm_debug("%s : %s %s/%d, Proto: %s, Metric: %u", label,
@@ -554,7 +555,7 @@ static void zfpm_log_route_info(netlink_route_info_t *ri, const char *label)
int zfpm_netlink_encode_route(int cmd, rib_dest_t *dest, struct route_entry *re,
char *in_buf, size_t in_buf_len)
{
- netlink_route_info_t ri_space, *ri;
+ struct netlink_route_info ri_space, *ri;
ri = &ri_space;
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index de044c0ea0..f24552c80b 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -1793,23 +1793,16 @@ static int nexthop_active(afi_t afi, struct route_entry *re,
nexthop->vrf_id);
return 0;
}
- if (connected_is_unnumbered(ifp)) {
- if (if_is_operative(ifp))
- return 1;
+ if (if_is_operative(ifp))
+ return 1;
+ else {
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
zlog_debug(
" %s: Onlink and interface %s is not operative",
__func__, ifp->name);
return 0;
}
- if (!if_is_operative(ifp)) {
- if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- zlog_debug(
- " %s: Interface %s is not unnumbered",
- __func__, ifp->name);
- return 0;
- }
}
if ((top->p.family == AF_INET && top->p.prefixlen == 32
@@ -2099,7 +2092,7 @@ static unsigned nexthop_active_check(struct route_node *rn,
* in every case.
*/
if (!family) {
- rib_table_info_t *info;
+ struct rib_table_info *info;
info = srcdest_rnode_table_info(rn);
family = info->afi;
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index f89656201c..ae730499ab 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -125,7 +125,7 @@ _rnode_zlog(const char *_func, vrf_id_t vrf_id, struct route_node *rn,
va_end(ap);
if (rn) {
- rib_table_info_t *info = srcdest_rnode_table_info(rn);
+ struct rib_table_info *info = srcdest_rnode_table_info(rn);
srcdest_rnode2str(rn, buf, sizeof(buf));
if (info->safi == SAFI_MULTICAST)
@@ -420,7 +420,7 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re,
struct route_entry *old)
{
struct nexthop *nexthop;
- rib_table_info_t *info = srcdest_rnode_table_info(rn);
+ struct rib_table_info *info = srcdest_rnode_table_info(rn);
struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id);
const struct prefix *p, *src_p;
enum zebra_dplane_result ret;
@@ -503,7 +503,7 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re,
void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re)
{
struct nexthop *nexthop;
- rib_table_info_t *info = srcdest_rnode_table_info(rn);
+ struct rib_table_info *info = srcdest_rnode_table_info(rn);
struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id);
if (info->safi != SAFI_UNICAST) {
@@ -546,7 +546,7 @@ void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re)
/* Uninstall the route from kernel. */
static void rib_uninstall(struct route_node *rn, struct route_entry *re)
{
- rib_table_info_t *info = srcdest_rnode_table_info(rn);
+ struct rib_table_info *info = srcdest_rnode_table_info(rn);
rib_dest_t *dest = rib_dest_from_rnode(rn);
struct nexthop *nexthop;
@@ -3085,7 +3085,7 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
return rib_add_multipath(afi, safi, p, src_p, re, ng);
}
-static const char *rib_update_event2str(rib_update_event_t event)
+static const char *rib_update_event2str(enum rib_update_event event)
{
const char *ret = "UNKNOWN";
@@ -3125,7 +3125,7 @@ static void rib_update_route_node(struct route_node *rn, int type)
}
/* Schedule routes of a particular table (address-family) based on event. */
-void rib_update_table(struct route_table *table, rib_update_event_t event)
+void rib_update_table(struct route_table *table, enum rib_update_event event)
{
struct route_node *rn;
@@ -3133,13 +3133,14 @@ void rib_update_table(struct route_table *table, rib_update_event_t event)
struct zebra_vrf *zvrf;
struct vrf *vrf;
- zvrf = table->info ? ((rib_table_info_t *)table->info)->zvrf
- : NULL;
+ zvrf = table->info
+ ? ((struct rib_table_info *)table->info)->zvrf
+ : NULL;
vrf = zvrf ? zvrf->vrf : NULL;
zlog_debug("%s: %s VRF %s Table %u event %s", __func__,
table->info ? afi2str(
- ((rib_table_info_t *)table->info)->afi)
+ ((struct rib_table_info *)table->info)->afi)
: "Unknown",
VRF_LOGNAME(vrf), zvrf ? zvrf->table_id : 0,
rib_update_event2str(event));
@@ -3173,7 +3174,7 @@ void rib_update_table(struct route_table *table, rib_update_event_t event)
}
}
-static void rib_update_handle_vrf(vrf_id_t vrf_id, rib_update_event_t event)
+static void rib_update_handle_vrf(vrf_id_t vrf_id, enum rib_update_event event)
{
struct route_table *table;
@@ -3191,7 +3192,7 @@ static void rib_update_handle_vrf(vrf_id_t vrf_id, rib_update_event_t event)
rib_update_table(table, event);
}
-static void rib_update_handle_vrf_all(rib_update_event_t event)
+static void rib_update_handle_vrf_all(enum rib_update_event event)
{
struct zebra_router_table *zrt;
@@ -3205,13 +3206,13 @@ static void rib_update_handle_vrf_all(rib_update_event_t event)
}
struct rib_update_ctx {
- rib_update_event_t event;
+ enum rib_update_event event;
bool vrf_all;
vrf_id_t vrf_id;
};
static struct rib_update_ctx *rib_update_ctx_init(vrf_id_t vrf_id,
- rib_update_event_t event)
+ enum rib_update_event event)
{
struct rib_update_ctx *ctx;
@@ -3251,7 +3252,7 @@ static int rib_update_handler(struct thread *thread)
static struct thread *t_rib_update_threads[RIB_UPDATE_MAX];
/* Schedule a RIB update event for specific vrf */
-void rib_update_vrf(vrf_id_t vrf_id, rib_update_event_t event)
+void rib_update_vrf(vrf_id_t vrf_id, enum rib_update_event event)
{
struct rib_update_ctx *ctx;
@@ -3271,7 +3272,7 @@ void rib_update_vrf(vrf_id_t vrf_id, rib_update_event_t event)
}
/* Schedule a RIB update event for all vrfs */
-void rib_update(rib_update_event_t event)
+void rib_update(enum rib_update_event event)
{
struct rib_update_ctx *ctx;
@@ -3425,7 +3426,7 @@ unsigned long rib_score_proto(uint8_t proto, unsigned short instance)
void rib_close_table(struct route_table *table)
{
struct route_node *rn;
- rib_table_info_t *info;
+ struct rib_table_info *info;
rib_dest_t *dest;
if (!table)
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index f9c74c7462..ad2e00b1ec 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -57,8 +57,8 @@ static void free_state(vrf_id_t vrf_id, struct route_entry *re,
static void copy_state(struct rnh *rnh, const struct route_entry *re,
struct route_node *rn);
static int compare_state(struct route_entry *r1, struct route_entry *r2);
-static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
- vrf_id_t vrf_id);
+static int send_client(struct rnh *rnh, struct zserv *client,
+ enum rnh_type type, vrf_id_t vrf_id);
static void print_rnh(struct route_node *rn, struct vty *vty);
static int zebra_client_cleanup_rnh(struct zserv *client);
@@ -68,7 +68,7 @@ void zebra_rnh_init(void)
}
static inline struct route_table *get_rnh_table(vrf_id_t vrfid, afi_t afi,
- rnh_type_t type)
+ enum rnh_type type)
{
struct zebra_vrf *zvrf;
struct route_table *t = NULL;
@@ -148,7 +148,7 @@ static void zebra_rnh_store_in_routing_table(struct rnh *rnh)
route_unlock_node(rn);
}
-struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type,
+struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, enum rnh_type type,
bool *exists)
{
struct route_table *table;
@@ -207,7 +207,8 @@ struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type,
return (rn->info);
}
-struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid, rnh_type_t type)
+struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid,
+ enum rnh_type type)
{
struct route_table *table;
struct route_node *rn;
@@ -258,7 +259,7 @@ void zebra_free_rnh(struct rnh *rnh)
XFREE(MTYPE_RNH, rnh);
}
-static void zebra_delete_rnh(struct rnh *rnh, rnh_type_t type)
+static void zebra_delete_rnh(struct rnh *rnh, enum rnh_type type)
{
struct route_node *rn;
@@ -289,7 +290,7 @@ static void zebra_delete_rnh(struct rnh *rnh, rnh_type_t type)
* and as such it will have a resolved rnh.
*/
void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client,
- rnh_type_t type, vrf_id_t vrf_id)
+ enum rnh_type type, vrf_id_t vrf_id)
{
if (IS_ZEBRA_DEBUG_NHT) {
char buf[PREFIX2STR_BUFFER];
@@ -308,7 +309,7 @@ void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client,
}
void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client,
- rnh_type_t type)
+ enum rnh_type type)
{
if (IS_ZEBRA_DEBUG_NHT) {
char buf[PREFIX2STR_BUFFER];
@@ -804,7 +805,7 @@ static void zebra_rnh_eval_nexthop_entry(struct zebra_vrf *zvrf, afi_t afi,
/* Evaluate one tracked entry */
static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, afi_t afi,
- int force, rnh_type_t type,
+ int force, enum rnh_type type,
struct route_node *nrn)
{
struct rnh *rnh;
@@ -851,7 +852,7 @@ static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, afi_t afi,
* covers multiple nexthops we are interested in.
*/
static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, afi_t afi,
- rnh_type_t type, struct route_node *nrn)
+ enum rnh_type type, struct route_node *nrn)
{
struct rnh *rnh;
struct route_entry *re;
@@ -875,7 +876,7 @@ static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, afi_t afi,
* of a particular VRF and address-family or a specific prefix.
*/
void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force,
- rnh_type_t type, struct prefix *p)
+ enum rnh_type type, struct prefix *p)
{
struct route_table *rnh_table;
struct route_node *nrn;
@@ -911,7 +912,7 @@ void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force,
}
void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty,
- rnh_type_t type, struct prefix *p)
+ enum rnh_type type, struct prefix *p)
{
struct route_table *table;
struct route_node *rn;
@@ -997,8 +998,8 @@ static int compare_state(struct route_entry *r1, struct route_entry *r2)
return 0;
}
-static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type,
- vrf_id_t vrf_id)
+static int send_client(struct rnh *rnh, struct zserv *client,
+ enum rnh_type type, vrf_id_t vrf_id)
{
struct stream *s;
struct route_entry *re;
@@ -1134,7 +1135,7 @@ static void print_rnh(struct route_node *rn, struct vty *vty)
}
static int zebra_cleanup_rnh_client(vrf_id_t vrf_id, afi_t afi,
- struct zserv *client, rnh_type_t type)
+ struct zserv *client, enum rnh_type type)
{
struct route_table *ntable;
struct route_node *nrn;
diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h
index 6e2dab8d9f..f07e5bc791 100644
--- a/zebra/zebra_rnh.h
+++ b/zebra/zebra_rnh.h
@@ -31,7 +31,7 @@ extern "C" {
extern void zebra_rnh_init(void);
-static inline const char *rnh_type2str(rnh_type_t type)
+static inline const char *rnh_type2str(enum rnh_type type)
{
switch (type) {
case RNH_NEXTHOP_TYPE:
@@ -44,20 +44,20 @@ static inline const char *rnh_type2str(rnh_type_t type)
}
extern struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid,
- rnh_type_t type, bool *exists);
+ enum rnh_type type, bool *exists);
extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid,
- rnh_type_t type);
+ enum rnh_type type);
extern void zebra_free_rnh(struct rnh *rnh);
extern void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client,
- rnh_type_t type, vrf_id_t vrfid);
+ enum rnh_type type, vrf_id_t vrfid);
extern void zebra_register_rnh_pseudowire(vrf_id_t, struct zebra_pw *);
extern void zebra_deregister_rnh_pseudowire(vrf_id_t, struct zebra_pw *);
extern void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client,
- rnh_type_t type);
+ enum rnh_type type);
extern void zebra_evaluate_rnh(struct zebra_vrf *zvrf, afi_t afi, int force,
- rnh_type_t type, struct prefix *p);
+ enum rnh_type type, struct prefix *p);
extern void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty,
- rnh_type_t type, struct prefix *p);
+ enum rnh_type type, struct prefix *p);
extern char *rnh_str(struct rnh *rnh, char *buf, int size);
extern int rnh_resolve_via_default(struct zebra_vrf *zvrf, int family);
diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c
index ea2b6752b3..ab426ae603 100644
--- a/zebra/zebra_router.c
+++ b/zebra/zebra_router.c
@@ -93,7 +93,7 @@ struct route_table *zebra_router_get_table(struct zebra_vrf *zvrf,
{
struct zebra_router_table finder;
struct zebra_router_table *zrt;
- rib_table_info_t *info;
+ struct rib_table_info *info;
memset(&finder, 0, sizeof(finder));
finder.afi = afi;
@@ -133,7 +133,7 @@ void zebra_router_show_table_summary(struct vty *vty)
vty_out(vty,
"---------------------------------------------------------------------------\n");
RB_FOREACH (zrt, zebra_router_table_head, &zrouter.tables) {
- rib_table_info_t *info = route_table_get_info(zrt->table);
+ struct rib_table_info *info = route_table_get_info(zrt->table);
vty_out(vty, "%-16s%5d %9d %7s %15s %8d %10lu\n", info->zvrf->vrf->name,
zrt->ns_id, info->zvrf->vrf->vrf_id,
diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h
index 268ee12a65..d262faa070 100644
--- a/zebra/zebra_vrf.h
+++ b/zebra/zebra_vrf.h
@@ -33,10 +33,10 @@ extern "C" {
#endif
/* MPLS (Segment Routing) global block */
-typedef struct mpls_srgb_t_ {
+struct mpls_srgb {
uint32_t start_label;
uint32_t end_label;
-} mpls_srgb_t;
+};
struct zebra_rmap {
char *name;
@@ -111,7 +111,7 @@ struct zebra_vrf {
struct route_table *fec_table[AFI_MAX];
/* MPLS Segment Routing Global block */
- mpls_srgb_t mpls_srgb;
+ struct mpls_srgb mpls_srgb;
/* Pseudowires. */
struct zebra_pw_head pseudowires;
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 8024db4ca7..7a0329a774 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -357,7 +357,8 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
const char *mcast_info = "";
if (mcast) {
- rib_table_info_t *info = srcdest_rnode_table_info(rn);
+ struct rib_table_info *info =
+ srcdest_rnode_table_info(rn);
mcast_info = (info->safi == SAFI_MULTICAST)
? " using Multicast RIB"
: " using Unicast RIB";
@@ -978,7 +979,7 @@ static void do_show_ip_route_all(struct vty *vty, struct zebra_vrf *zvrf,
unsigned short ospf_instance_id)
{
struct zebra_router_table *zrt;
- rib_table_info_t *info;
+ struct rib_table_info *info;
RB_FOREACH (zrt, zebra_router_table_head,
&zrouter.tables) {
@@ -1059,7 +1060,7 @@ DEFPY (show_ip_nht,
afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
vrf_id_t vrf_id = VRF_DEFAULT;
struct prefix prefix, *p = NULL;
- rnh_type_t rtype;
+ enum rnh_type rtype;
if (strcmp(type, "nht") == 0)
rtype = RNH_NEXTHOP_TYPE;
@@ -1832,8 +1833,8 @@ static void vty_show_ip_route_summary(struct vty *vty,
if (!use_json)
vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source",
"Routes", "FIB",
- zvrf_name(((rib_table_info_t *)route_table_get_info(
- table))
+ zvrf_name(((struct rib_table_info *)
+ route_table_get_info(table))
->zvrf));
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
@@ -1980,8 +1981,8 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty,
if (!use_json)
vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source",
"Prefix Routes", "FIB",
- zvrf_name(((rib_table_info_t *)route_table_get_info(
- table))
+ zvrf_name(((struct rib_table_info *)
+ route_table_get_info(table))
->zvrf));
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {