summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--babeld/babel_filter.c7
-rw-r--r--babeld/babel_interface.c9
-rw-r--r--babeld/babeld.c29
-rw-r--r--babeld/babeld.h4
-rw-r--r--bgpd/bgp_attr.c8
-rw-r--r--bgpd/bgp_evpn_vty.c30
-rw-r--r--bgpd/bgp_packet.c10
-rw-r--r--bgpd/bgp_route.c9
-rw-r--r--bgpd/bgpd.conf.sample4
-rw-r--r--bgpd/bgpd.h2
-rw-r--r--doc/user/sharp.rst10
-rw-r--r--eigrpd/eigrp_dump.c5
-rw-r--r--eigrpd/eigrp_filter.c12
-rw-r--r--eigrpd/eigrp_filter.h3
-rw-r--r--eigrpd/eigrp_main.c2
-rw-r--r--eigrpd/eigrp_network.c4
-rw-r--r--eigrpd/eigrp_structs.h7
-rw-r--r--eigrpd/eigrp_vty.c29
-rw-r--r--eigrpd/eigrpd.c24
-rw-r--r--isisd/isis_northbound.c5
-rw-r--r--lib/distribute.c155
-rw-r--r--lib/distribute.h36
-rw-r--r--lib/mlag.c41
-rw-r--r--lib/mlag.h32
-rw-r--r--lib/northbound_cli.c13
-rw-r--r--lib/northbound_cli.h2
-rw-r--r--lib/subdir.am2
-rw-r--r--lib/vrf.c2
-rw-r--r--lib/zclient.c13
-rw-r--r--lib/zclient.h3
-rw-r--r--ospfd/ospf_vty.c42
-rw-r--r--pimd/pim_assert.c2
-rw-r--r--pimd/pim_cmd.c21
-rw-r--r--pimd/pim_iface.c2
-rw-r--r--pimd/pim_ifchannel.c33
-rw-r--r--pimd/pim_igmp.c14
-rw-r--r--pimd/pim_igmpv3.c7
-rw-r--r--pimd/pim_instance.c8
-rw-r--r--pimd/pim_instance.h24
-rw-r--r--pimd/pim_macro.c2
-rw-r--r--pimd/pim_main.c4
-rw-r--r--pimd/pim_mroute.c4
-rw-r--r--pimd/pim_msdp.c9
-rw-r--r--pimd/pim_msdp.h5
-rw-r--r--pimd/pim_msdp_socket.c2
-rw-r--r--pimd/pim_neighbor.c12
-rw-r--r--pimd/pim_pim.c12
-rw-r--r--pimd/pim_ssmpingd.c2
-rw-r--r--pimd/pim_upstream.c24
-rw-r--r--pimd/pim_upstream.h5
-rw-r--r--pimd/pim_vty.c14
-rw-r--r--pimd/pim_zebra.c16
-rw-r--r--pimd/pim_zlookup.c6
-rw-r--r--pimd/pimd.c63
-rw-r--r--pimd/pimd.h193
-rw-r--r--ripd/ripd.c31
-rw-r--r--ripd/ripd.h4
-rw-r--r--ripngd/ripngd.c29
-rw-r--r--ripngd/ripngd.h4
-rw-r--r--sharpd/sharp_main.c2
-rw-r--r--sharpd/sharp_vty.c97
-rw-r--r--sharpd/sharp_zebra.c101
-rw-r--r--sharpd/sharp_zebra.h9
-rw-r--r--staticd/static_zebra.c4
-rw-r--r--tests/topotests/bgp_rfapi_basic_sanity/r1/bgpd.conf2
-rw-r--r--tests/topotests/bgp_rfapi_basic_sanity/r3/bgpd.conf2
-rw-r--r--tests/topotests/bgp_rfapi_basic_sanity/r4/bgpd.conf2
-rw-r--r--tests/topotests/bgp_rfapi_basic_sanity_config2/r1/bgpd.conf2
-rw-r--r--tests/topotests/bgp_rfapi_basic_sanity_config2/r3/bgpd.conf2
-rw-r--r--tests/topotests/bgp_rfapi_basic_sanity_config2/r4/bgpd.conf2
-rwxr-xr-xvtysh/extract.pl.in2
-rw-r--r--vtysh/vtysh.c5
-rw-r--r--zebra/if_netlink.c2
-rw-r--r--zebra/kernel_netlink.c11
-rw-r--r--zebra/kernel_socket.c35
-rw-r--r--zebra/subdir.am7
-rw-r--r--zebra/zapi_msg.c6
-rw-r--r--zebra/zebra_mlag.c83
-rw-r--r--zebra/zebra_mlag.h31
-rw-r--r--zebra/zebra_ns.c1
-rw-r--r--zebra/zebra_router.c5
-rw-r--r--zebra/zebra_vxlan.c35
82 files changed, 1045 insertions, 509 deletions
diff --git a/babeld/babel_filter.c b/babeld/babel_filter.c
index 31778901a6..28ba8e16a2 100644
--- a/babeld/babel_filter.c
+++ b/babeld/babel_filter.c
@@ -39,10 +39,11 @@ babel_filter(int output, const unsigned char *prefix, unsigned short plen,
struct interface *ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
babel_interface_nfo *babel_ifp = ifp ? babel_get_if_nfo(ifp) : NULL;
struct prefix p;
- struct distribute *dist;
+ struct distribute *dist = NULL;
struct access_list *alist;
struct prefix_list *plist;
int distribute;
+ struct babel *babel;
p.family = v4mapped(prefix) ? AF_INET : AF_INET6;
p.prefixlen = v4mapped(prefix) ? plen - 96 : plen;
@@ -81,7 +82,9 @@ babel_filter(int output, const unsigned char *prefix, unsigned short plen,
}
/* All interface filter check. */
- dist = distribute_lookup (NULL);
+ babel = babel_lookup();
+ if (babel)
+ dist = distribute_lookup (babel->distribute_ctx, NULL);
if (dist) {
if (dist->list[distribute]) {
alist = access_list_lookup (p.family, dist->list[distribute]);
diff --git a/babeld/babel_interface.c b/babeld/babel_interface.c
index 7121ca28d4..a8698bfce3 100644
--- a/babeld/babel_interface.c
+++ b/babeld/babel_interface.c
@@ -1248,11 +1248,16 @@ DEFUN (show_babel_parameters,
"Babel information\n"
"Configuration information\n")
{
+ struct babel *babel_ctx;
+
vty_out (vty, " -- Babel running configuration --\n");
show_babel_main_configuration(vty);
- vty_out (vty, " -- distribution lists --\n");
- config_show_distribute(vty);
+ babel_ctx = babel_lookup();
+ if (babel_ctx) {
+ vty_out (vty, " -- distribution lists --\n");
+ config_show_distribute(vty, babel_ctx->distribute_ctx);
+ }
return CMD_SUCCESS;
}
diff --git a/babeld/babeld.c b/babeld/babeld.c
index 0517cbea6d..702c1fbabb 100644
--- a/babeld/babeld.c
+++ b/babeld/babeld.c
@@ -53,7 +53,8 @@ static int babel_read_protocol (struct thread *thread);
static int babel_main_loop(struct thread *thread);
static void babel_set_timer(struct timeval *timeout);
static void babel_fill_with_next_timeout(struct timeval *tv);
-
+static void
+babel_distribute_update (struct distribute_ctx *ctx, struct distribute *dist);
/* Informations relative to the babel running daemon. */
static struct babel *babel_routing_process = NULL;
@@ -123,7 +124,7 @@ babel_config_write (struct vty *vty)
}
}
- lines += config_write_distribute (vty);
+ lines += config_write_distribute (vty, babel_routing_process->distribute_ctx);
return lines;
}
@@ -154,8 +155,12 @@ babel_create_routing_process (void)
thread_add_read(master, &babel_read_protocol, NULL, protocol_socket, &babel_routing_process->t_read);
/* wait a little: zebra will announce interfaces, addresses, routes... */
thread_add_timer_msec(master, babel_init_routing_process, NULL, 200L, &babel_routing_process->t_update);
- return 0;
+ /* Distribute list install. */
+ babel_routing_process->distribute_ctx = distribute_list_ctx_create (vrf_lookup_by_id(VRF_DEFAULT));
+ distribute_list_add_hook (babel_routing_process->distribute_ctx, babel_distribute_update);
+ distribute_list_delete_hook (babel_routing_process->distribute_ctx, babel_distribute_update);
+ return 0;
fail:
XFREE(MTYPE_BABEL, babel_routing_process);
babel_routing_process = NULL;
@@ -315,6 +320,7 @@ babel_clean_routing_process()
thread_cancel(babel_routing_process->t_update);
}
+ distribute_list_delete(&babel_routing_process->distribute_ctx);
XFREE(MTYPE_BABEL, babel_routing_process);
babel_routing_process = NULL;
}
@@ -539,7 +545,7 @@ resize_receive_buffer(int size)
}
static void
-babel_distribute_update (struct distribute *dist)
+babel_distribute_update (struct distribute_ctx *ctx, struct distribute *dist)
{
struct interface *ifp;
babel_interface_nfo *babel_ifp;
@@ -574,11 +580,12 @@ babel_distribute_update (struct distribute *dist)
static void
babel_distribute_update_interface (struct interface *ifp)
{
- struct distribute *dist;
+ struct distribute *dist = NULL;
- dist = distribute_lookup (ifp->name);
+ if (babel_routing_process)
+ dist = distribute_lookup(babel_routing_process->distribute_ctx, ifp->name);
if (dist)
- babel_distribute_update (dist);
+ babel_distribute_update (babel_routing_process->distribute_ctx, dist);
}
/* Update all interface's distribute list. */
@@ -736,9 +743,7 @@ babeld_quagga_init(void)
prefix_list_delete_hook (babel_distribute_update_all);
/* Distribute list install. */
- distribute_list_init (BABEL_NODE);
- distribute_list_add_hook (babel_distribute_update);
- distribute_list_delete_hook (babel_distribute_update);
+ distribute_list_init(BABEL_NODE);
}
/* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */
@@ -767,3 +772,7 @@ redistribute_filter(const unsigned char *prefix, unsigned short plen,
return 0;
}
+struct babel *babel_lookup(void)
+{
+ return babel_routing_process;
+}
diff --git a/babeld/babeld.h b/babeld/babeld.h
index bc284c1e96..752cc8620a 100644
--- a/babeld/babeld.h
+++ b/babeld/babeld.h
@@ -111,6 +111,8 @@ struct babel
/* Babel threads. */
struct thread *t_read; /* on Babel protocol's socket */
struct thread *t_update; /* timers */
+ /* distribute_ctx */
+ struct distribute_ctx *distribute_ctx;
};
extern struct zebra_privs_t babeld_privs;
@@ -125,6 +127,6 @@ extern int redistribute_filter(const unsigned char *prefix, unsigned short plen,
unsigned int ifindex, int proto);
extern int resize_receive_buffer(int size);
extern void schedule_neighbours_check(int msecs, int override);
-
+extern struct babel *babel_lookup(void);
#endif /* BABEL_BABELD_H */
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 87ebb9c285..b990e99bda 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -78,7 +78,7 @@ static const struct message attr_str[] = {
{BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT"},
{BGP_ATTR_PMSI_TUNNEL, "PMSI_TUNNEL_ATTRIBUTE"},
{BGP_ATTR_ENCAP, "ENCAP"},
-#if ENABLE_BGP_VNC
+#if ENABLE_BGP_VNC_ATTR
{BGP_ATTR_VNC, "VNC"},
#endif
{BGP_ATTR_LARGE_COMMUNITIES, "LARGE_COMMUNITY"},
@@ -2593,7 +2593,7 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
case BGP_ATTR_EXT_COMMUNITIES:
ret = bgp_attr_ext_communities(&attr_args);
break;
-#if ENABLE_BGP_VNC
+#if ENABLE_BGP_VNC_ATTR
case BGP_ATTR_VNC:
#endif
case BGP_ATTR_ENCAP:
@@ -2946,7 +2946,7 @@ static void bgp_packet_mpattr_tea(struct bgp *bgp, struct peer *peer,
attrhdrlen = 1 + 1; /* subTLV T + L */
break;
-#if ENABLE_BGP_VNC
+#if ENABLE_BGP_VNC_ATTR
case BGP_ATTR_VNC:
attrname = "VNC";
subtlvs = attr->vnc_subtlvs;
@@ -3433,7 +3433,7 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
/* Tunnel Encap attribute */
bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_ENCAP);
-#if ENABLE_BGP_VNC
+#if ENABLE_BGP_VNC_ATTR
/* VNC attribute */
bgp_packet_mpattr_tea(bgp, peer, s, attr, BGP_ATTR_VNC);
#endif
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c
index 13f899e880..776f8f8ef7 100644
--- a/bgpd/bgp_evpn_vty.c
+++ b/bgpd/bgp_evpn_vty.c
@@ -2883,6 +2883,12 @@ DEFUN (bgp_evpn_advertise_default_gw,
if (!bgp)
return CMD_WARNING;
+ if (bgp->vrf_id != VRF_DEFAULT) {
+ vty_out(vty,
+ "This command is only supported under Default VRF\n");
+ return CMD_WARNING;
+ }
+
evpn_set_advertise_default_gw(bgp, NULL);
return CMD_SUCCESS;
@@ -2899,6 +2905,12 @@ DEFUN (no_bgp_evpn_advertise_default_gw,
if (!bgp)
return CMD_WARNING;
+ if (bgp->vrf_id != VRF_DEFAULT) {
+ vty_out(vty,
+ "This command is only supported under Default VRF\n");
+ return CMD_WARNING;
+ }
+
evpn_unset_advertise_default_gw(bgp, NULL);
return CMD_SUCCESS;
@@ -3011,6 +3023,12 @@ DEFPY (dup_addr_detection,
if (!bgp_vrf)
return CMD_WARNING;
+ if (bgp_vrf->vrf_id != VRF_DEFAULT) {
+ vty_out(vty,
+ "This command is only supported under Default VRF\n");
+ return CMD_WARNING;
+ }
+
bgp_vrf->evpn_info->dup_addr_detect = true;
if (time_val)
@@ -3037,6 +3055,12 @@ DEFPY (dup_addr_detection_auto_recovery,
if (!bgp_vrf)
return CMD_WARNING;
+ if (bgp_vrf->vrf_id != VRF_DEFAULT) {
+ vty_out(vty,
+ "This command is only supported under Default VRF\n");
+ return CMD_WARNING;
+ }
+
bgp_vrf->evpn_info->dup_addr_detect = true;
bgp_vrf->evpn_info->dad_freeze = true;
bgp_vrf->evpn_info->dad_freeze_time = freeze_time;
@@ -3066,6 +3090,12 @@ DEFPY (no_dup_addr_detection,
if (!bgp_vrf)
return CMD_WARNING;
+ if (bgp_vrf->vrf_id != VRF_DEFAULT) {
+ vty_out(vty,
+ "This command is only supported under Default VRF\n");
+ return CMD_WARNING;
+ }
+
if (argc == 2) {
if (!bgp_vrf->evpn_info->dup_addr_detect)
return CMD_SUCCESS;
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 73a07c8232..7b76d7e83e 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -1612,6 +1612,8 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
}
if (afi && peer->afc[afi][safi]) {
+ struct vrf *vrf = vrf_lookup_by_id(peer->bgp->vrf_id);
+
/* End-of-RIB received */
if (!CHECK_FLAG(peer->af_sflags[afi][safi],
PEER_STATUS_EOR_RECEIVED)) {
@@ -1624,11 +1626,9 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
if (peer->nsf[afi][safi])
bgp_clear_stale_route(peer, afi, safi);
- if (bgp_debug_neighbor_events(peer)) {
- zlog_debug("rcvd End-of-RIB for %s from %s",
- afi_safi_print(afi, safi),
- peer->host);
- }
+ zlog_info("%%NOTIFICATION: rcvd End-of-RIB for %s from %s in vrf %s",
+ afi_safi_print(afi, safi), peer->host,
+ vrf ? vrf->name : VRF_DEFAULT_NAME);
}
}
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 2c361bef4d..31cd3d1f05 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -9529,9 +9529,16 @@ DEFUN (show_ip_bgp_json,
}
if (argv_find(argv, argc, "community", &idx)) {
- char *maybecomm = idx + 1 < argc ? argv[idx + 1]->text : NULL;
+ char *maybecomm = NULL;
char *community = NULL;
+ if (idx + 1 < argc) {
+ if (argv[idx + 1]->type == VARIABLE_TKN)
+ maybecomm = argv[idx + 1]->arg;
+ else
+ maybecomm = argv[idx + 1]->text;
+ }
+
if (maybecomm && !strmatch(maybecomm, "json")
&& !strmatch(maybecomm, "exact-match"))
community = maybecomm;
diff --git a/bgpd/bgpd.conf.sample b/bgpd/bgpd.conf.sample
index 60a74a71ef..cb12a92522 100644
--- a/bgpd/bgpd.conf.sample
+++ b/bgpd/bgpd.conf.sample
@@ -1,6 +1,6 @@
! -*- bgp -*-
!
-! BGPd sample configuratin file
+! BGPd sample configuration file
!
! $Id: bgpd.conf.sample,v 1.1 2002/12/13 20:15:29 paul Exp $
!
@@ -8,7 +8,7 @@ hostname bgpd
password zebra
!enable password please-set-at-here
!
-!bgp mulitple-instance
+!bgp multiple-instance
!
router bgp 7675
! bgp router-id 10.0.0.1
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 62096d651a..f28ca9fa0b 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -1280,7 +1280,7 @@ struct bgp_nlri {
#define BGP_ATTR_ENCAP 23
#define BGP_ATTR_LARGE_COMMUNITIES 32
#define BGP_ATTR_PREFIX_SID 40
-#if ENABLE_BGP_VNC
+#if ENABLE_BGP_VNC_ATTR
#define BGP_ATTR_VNC 255
#endif
diff --git a/doc/user/sharp.rst b/doc/user/sharp.rst
index 8831c0159b..c2d32a718e 100644
--- a/doc/user/sharp.rst
+++ b/doc/user/sharp.rst
@@ -33,16 +33,20 @@ All sharp commands are under the enable node and preceeded by the ``sharp``
keyword. At present, no sharp commands will be preserved in the config.
.. index:: sharp install
-.. clicmd:: sharp install routes A.B.C.D nexthop <E.F.G.H|X:X::X:X> (1-1000000)
+.. clicmd:: sharp install routes A.B.C.D <nexthop <E.F.G.H|X:X::X:X>|nexthop-group NAME> (1-1000000) [instance (0-255)] [repeat (2-1000)]
Install up to 1,000,000 (one million) /32 routes starting at ``A.B.C.D``
with specified nexthop ``E.F.G.H`` or ``X:X::X:X``. The nexthop is
a ``NEXTHOP_TYPE_IPV4`` or ``NEXTHOP_TYPE_IPV6`` and must be reachable
- to be installed into the kernel. The routes are installed into zebra as
- ``ZEBRA_ROUTE_SHARP`` and can be used as part of a normal route
+ to be installed into the kernel. Alternatively a nexthop-group NAME
+ can be specified and used as the nexthops. The routes are installed into
+ zebra as ``ZEBRA_ROUTE_SHARP`` and can be used as part of a normal route
redistribution. Route installation time is noted in the debug
log. When zebra successfully installs a route into the kernel and SHARP
receives success notifications for all routes this is logged as well.
+ Instance (0-255) if specified causes the routes to be installed in a different
+ instance. If repeat is used then we will install/uninstall the routes the
+ number of times specified.
.. index:: sharp remove
.. clicmd:: sharp remove routes A.B.C.D (1-1000000)
diff --git a/eigrpd/eigrp_dump.c b/eigrpd/eigrp_dump.c
index 27e02630a6..c975c0abc7 100644
--- a/eigrpd/eigrp_dump.c
+++ b/eigrpd/eigrp_dump.c
@@ -276,11 +276,8 @@ void show_ip_eigrp_neighbor_sub(struct vty *vty, struct eigrp_neighbor *nbr,
*/
void show_ip_eigrp_topology_header(struct vty *vty, struct eigrp *eigrp)
{
- struct in_addr router_id;
- router_id.s_addr = eigrp->router_id;
-
vty_out(vty, "\nEIGRP Topology Table for AS(%d)/ID(%s)\n\n", eigrp->AS,
- inet_ntoa(router_id));
+ inet_ntoa(eigrp->router_id));
vty_out(vty,
"Codes: P - Passive, A - Active, U - Update, Q - Query, "
"R - Reply\n r - reply Status, s - sia Status\n\n");
diff --git a/eigrpd/eigrp_filter.c b/eigrpd/eigrp_filter.c
index c1bf1647d8..93eed9452c 100644
--- a/eigrpd/eigrp_filter.c
+++ b/eigrpd/eigrp_filter.c
@@ -62,7 +62,8 @@
/*
* Distribute-list update functions.
*/
-void eigrp_distribute_update(struct distribute *dist)
+void eigrp_distribute_update(struct distribute_ctx *ctx,
+ struct distribute *dist)
{
struct interface *ifp;
struct eigrp_interface *ei = NULL;
@@ -285,10 +286,15 @@ void eigrp_distribute_update(struct distribute *dist)
void eigrp_distribute_update_interface(struct interface *ifp)
{
struct distribute *dist;
+ struct eigrp *eigrp;
- dist = distribute_lookup(ifp->name);
+ eigrp = eigrp_lookup();
+ if (!eigrp)
+ return;
+ dist = distribute_lookup(eigrp->distribute_ctx, ifp->name);
if (dist)
- eigrp_distribute_update(dist);
+ eigrp_distribute_update(eigrp->distribute_ctx,
+ dist);
}
/* Update all interface's distribute list.
diff --git a/eigrpd/eigrp_filter.h b/eigrpd/eigrp_filter.h
index caec19b0fb..34d00ecc13 100644
--- a/eigrpd/eigrp_filter.h
+++ b/eigrpd/eigrp_filter.h
@@ -33,7 +33,8 @@
#ifndef EIGRPD_EIGRP_FILTER_H_
#define EIGRPD_EIGRP_FILTER_H_
-extern void eigrp_distribute_update(struct distribute *);
+extern void eigrp_distribute_update(struct distribute_ctx *ctx,
+ struct distribute *dist);
extern void eigrp_distribute_update_interface(struct interface *);
extern void eigrp_distribute_update_all(struct prefix_list *);
extern void eigrp_distribute_update_all_wrapper(struct access_list *);
diff --git a/eigrpd/eigrp_main.c b/eigrpd/eigrp_main.c
index 063fc5fec1..b19b383e65 100644
--- a/eigrpd/eigrp_main.c
+++ b/eigrpd/eigrp_main.c
@@ -217,8 +217,6 @@ int main(int argc, char **argv, char **envp)
/* Distribute list install. */
distribute_list_init(EIGRP_NODE);
- distribute_list_add_hook(eigrp_distribute_update);
- distribute_list_delete_hook(eigrp_distribute_update);
frr_config_fork();
frr_run(master);
diff --git a/eigrpd/eigrp_network.c b/eigrpd/eigrp_network.c
index 35b45288b8..6bb619f0e1 100644
--- a/eigrpd/eigrp_network.c
+++ b/eigrpd/eigrp_network.c
@@ -227,7 +227,7 @@ int eigrp_network_set(struct eigrp *eigrp, struct prefix *p)
rn->info = (void *)pref;
/* Schedule Router ID Update. */
- if (eigrp->router_id == 0)
+ if (eigrp->router_id.s_addr == 0)
eigrp_router_id_update(eigrp);
/* Run network config now. */
/* Get target interface. */
@@ -293,7 +293,7 @@ void eigrp_if_update(struct interface *ifp)
*/
for (ALL_LIST_ELEMENTS(eigrp_om->eigrp, node, nnode, eigrp)) {
/* EIGRP must be on and Router-ID must be configured. */
- if (!eigrp || eigrp->router_id == 0)
+ if (!eigrp || eigrp->router_id.s_addr == 0)
continue;
/* Run each network for this interface. */
diff --git a/eigrpd/eigrp_structs.h b/eigrpd/eigrp_structs.h
index ce03a21fba..644ab0829f 100644
--- a/eigrpd/eigrp_structs.h
+++ b/eigrpd/eigrp_structs.h
@@ -79,8 +79,8 @@ struct eigrp {
char *name;
/* EIGRP Router ID. */
- uint32_t router_id; /* Configured automatically. */
- uint32_t router_id_static; /* Configured manually. */
+ struct in_addr router_id; /* Configured automatically. */
+ struct in_addr router_id_static; /* Configured manually. */
struct list *eiflist; /* eigrp interfaces */
uint8_t passive_interface_default; /* passive-interface default */
@@ -131,6 +131,9 @@ struct eigrp {
uint32_t metric;
} route_map[ZEBRA_ROUTE_MAX];
+ /* distribute_ctx */
+ struct distribute_ctx *distribute_ctx;
+
QOBJ_FIELDS
};
DECLARE_QOBJ_TYPE(eigrp)
diff --git a/eigrpd/eigrp_vty.c b/eigrpd/eigrp_vty.c
index a0c4fa887a..474f683989 100644
--- a/eigrpd/eigrp_vty.c
+++ b/eigrpd/eigrp_vty.c
@@ -174,7 +174,7 @@ static int config_write_eigrp_distribute(struct vty *vty, struct eigrp *eigrp)
int write = 0;
/* Distribute configuration. */
- write += config_write_distribute(vty);
+ write += config_write_distribute(vty, eigrp->distribute_ctx);
return write;
}
@@ -191,15 +191,10 @@ static int config_write_eigrp_router(struct vty *vty, struct eigrp *eigrp)
write++;
- if (!eigrp->networks)
- return write;
-
/* Router ID print. */
- if (eigrp->router_id_static != 0) {
- struct in_addr router_id_static;
- router_id_static.s_addr = htonl(eigrp->router_id_static);
+ if (eigrp->router_id_static.s_addr != 0) {
vty_out(vty, " eigrp router-id %s\n",
- inet_ntoa(router_id_static));
+ inet_ntoa(eigrp->router_id_static));
}
/* Network area print. */
@@ -255,29 +250,31 @@ DEFUN (no_router_eigrp,
return CMD_SUCCESS;
}
-DEFUN (eigrp_router_id,
+DEFPY (eigrp_router_id,
eigrp_router_id_cmd,
- "eigrp router-id A.B.C.D",
+ "eigrp router-id A.B.C.D$addr",
"EIGRP specific commands\n"
"Router ID for this EIGRP process\n"
"EIGRP Router-ID in IP address format\n")
{
- // struct eigrp *eigrp = vty->index;
- /*TODO: */
+ VTY_DECLVAR_CONTEXT(eigrp, eigrp);
+
+ eigrp->router_id_static = addr;
return CMD_SUCCESS;
}
-DEFUN (no_eigrp_router_id,
+DEFPY (no_eigrp_router_id,
no_eigrp_router_id_cmd,
- "no eigrp router-id A.B.C.D",
+ "no eigrp router-id [A.B.C.D$addr]",
NO_STR
"EIGRP specific commands\n"
"Router ID for this EIGRP process\n"
"EIGRP Router-ID in IP address format\n")
{
- // struct eigrp *eigrp = vty->index;
- /*TODO: */
+ VTY_DECLVAR_CONTEXT(eigrp, eigrp);
+
+ eigrp->router_id_static.s_addr = 0;
return CMD_SUCCESS;
}
diff --git a/eigrpd/eigrpd.c b/eigrpd/eigrpd.c
index 9bbecdf9e3..5541ec15f3 100644
--- a/eigrpd/eigrpd.c
+++ b/eigrpd/eigrpd.c
@@ -44,6 +44,7 @@
#include "keychain.h"
#include "libfrr.h"
#include "lib_errors.h"
+#include "distribute.h"
#include "eigrpd/eigrp_structs.h"
#include "eigrpd/eigrpd.h"
@@ -55,6 +56,7 @@
#include "eigrpd/eigrp_network.h"
#include "eigrpd/eigrp_topology.h"
#include "eigrpd/eigrp_memory.h"
+#include "eigrpd/eigrp_filter.h"
DEFINE_QOBJ_TYPE(eigrp)
@@ -95,21 +97,21 @@ void eigrp_router_id_update(struct eigrp *eigrp)
{
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
- uint32_t router_id, router_id_old;
+ struct in_addr router_id, router_id_old;
router_id_old = eigrp->router_id;
- if (eigrp->router_id_static != 0)
+ if (eigrp->router_id_static.s_addr != 0)
router_id = eigrp->router_id_static;
- else if (eigrp->router_id != 0)
+ else if (eigrp->router_id.s_addr != 0)
router_id = eigrp->router_id;
else
- router_id = router_id_zebra.s_addr;
+ router_id = router_id_zebra;
eigrp->router_id = router_id;
- if (router_id_old != router_id) {
+ if (router_id_old.s_addr != router_id.s_addr) {
// if (IS_DEBUG_EIGRP_EVENT)
// zlog_debug("Router-ID[NEW:%s]: Update",
// inet_ntoa(eigrp->router_id));
@@ -142,8 +144,8 @@ static struct eigrp *eigrp_new(const char *AS)
/* init information relevant to peers */
eigrp->vrid = 0;
eigrp->AS = atoi(AS);
- eigrp->router_id = 0L;
- eigrp->router_id_static = 0L;
+ eigrp->router_id.s_addr = 0;
+ eigrp->router_id_static.s_addr = 0;
eigrp->sequence_number = 1;
/*Configure default K Values for EIGRP Process*/
@@ -197,6 +199,13 @@ static struct eigrp *eigrp_new(const char *AS)
eigrp->routemap[EIGRP_FILTER_IN] = NULL;
eigrp->routemap[EIGRP_FILTER_OUT] = NULL;
+ /* Distribute list install. */
+ eigrp->distribute_ctx = distribute_list_ctx_create(
+ vrf_lookup_by_id(VRF_DEFAULT));
+ distribute_list_add_hook(eigrp->distribute_ctx,
+ eigrp_distribute_update);
+ distribute_list_delete_hook(eigrp->distribute_ctx,
+ eigrp_distribute_update);
QOBJ_REG(eigrp, eigrp);
return eigrp;
}
@@ -279,6 +288,7 @@ void eigrp_finish_final(struct eigrp *eigrp)
listnode_delete(eigrp_om->eigrp, eigrp);
stream_free(eigrp->ibuf);
+ distribute_list_delete(&eigrp->distribute_ctx);
XFREE(MTYPE_EIGRP_TOP, eigrp);
}
diff --git a/isisd/isis_northbound.c b/isisd/isis_northbound.c
index a467282826..9c2bb1728e 100644
--- a/isisd/isis_northbound.c
+++ b/isisd/isis_northbound.c
@@ -1982,11 +1982,10 @@ static int lib_interface_isis_network_type_modify(enum nb_event event,
circuit = yang_dnode_get_entry(dnode, false);
if (!circuit)
break;
- if (circuit->circ_type == CIRCUIT_T_LOOPBACK
- || circuit->circ_type == CIRCUIT_T_UNKNOWN) {
+ if (circuit->circ_type == CIRCUIT_T_LOOPBACK) {
flog_warn(
EC_LIB_NB_CB_CONFIG_VALIDATE,
- "Cannot change network type on unknown or loopback interface");
+ "Cannot change network type on loopback interface");
return NB_ERR_VALIDATION;
}
if (net_type == CIRCUIT_T_BROADCAST
diff --git a/lib/distribute.c b/lib/distribute.c
index 9697916332..3a6b775bc8 100644
--- a/lib/distribute.c
+++ b/lib/distribute.c
@@ -27,16 +27,12 @@
#include "distribute.h"
#include "memory.h"
+DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE_CTX, "Distribute ctx")
DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE, "Distribute list")
DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE_IFNAME, "Dist-list ifname")
DEFINE_MTYPE_STATIC(LIB, DISTRIBUTE_NAME, "Dist-list name")
-/* Hash of distribute list. */
-struct hash *disthash;
-
-/* Hook functions. */
-void (*distribute_add_hook)(struct distribute *);
-void (*distribute_delete_hook)(struct distribute *);
+struct list *dist_ctx_list;
static struct distribute *distribute_new(void)
{
@@ -62,7 +58,8 @@ static void distribute_free(struct distribute *dist)
XFREE(MTYPE_DISTRIBUTE, dist);
}
-static void distribute_free_if_empty(struct distribute *dist)
+static void distribute_free_if_empty(struct distribute_ctx *ctx,
+ struct distribute *dist)
{
int i;
@@ -70,12 +67,13 @@ static void distribute_free_if_empty(struct distribute *dist)
if (dist->list[i] != NULL || dist->prefix[i] != NULL)
return;
- hash_release(disthash, dist);
+ hash_release(ctx->disthash, dist);
distribute_free(dist);
}
/* Lookup interface's distribute list. */
-struct distribute *distribute_lookup(const char *ifname)
+struct distribute *distribute_lookup(struct distribute_ctx *ctx,
+ const char *ifname)
{
struct distribute key;
struct distribute *dist;
@@ -83,7 +81,7 @@ struct distribute *distribute_lookup(const char *ifname)
/* temporary reference */
key.ifname = (ifname) ? XSTRDUP(MTYPE_DISTRIBUTE_IFNAME, ifname) : NULL;
- dist = hash_lookup(disthash, &key);
+ dist = hash_lookup(ctx->disthash, &key);
if (key.ifname)
XFREE(MTYPE_DISTRIBUTE_IFNAME, key.ifname);
@@ -91,14 +89,18 @@ struct distribute *distribute_lookup(const char *ifname)
return dist;
}
-void distribute_list_add_hook(void (*func)(struct distribute *))
+void distribute_list_add_hook(struct distribute_ctx *ctx,
+ void (*func)(struct distribute_ctx *ctx,
+ struct distribute *))
{
- distribute_add_hook = func;
+ ctx->distribute_add_hook = func;
}
-void distribute_list_delete_hook(void (*func)(struct distribute *))
+void distribute_list_delete_hook(struct distribute_ctx *ctx,
+ void (*func)(struct distribute_ctx *ctx,
+ struct distribute *))
{
- distribute_delete_hook = func;
+ ctx->distribute_delete_hook = func;
}
static void *distribute_hash_alloc(struct distribute *arg)
@@ -114,7 +116,8 @@ static void *distribute_hash_alloc(struct distribute *arg)
}
/* Make new distribute list and push into hash. */
-static struct distribute *distribute_get(const char *ifname)
+static struct distribute *distribute_get(struct distribute_ctx *ctx,
+ const char *ifname)
{
struct distribute key;
struct distribute *ret;
@@ -122,7 +125,7 @@ static struct distribute *distribute_get(const char *ifname)
/* temporary reference */
key.ifname = (ifname) ? XSTRDUP(MTYPE_DISTRIBUTE_IFNAME, ifname) : NULL;
- ret = hash_get(disthash, &key,
+ ret = hash_get(ctx->disthash, &key,
(void *(*)(void *))distribute_hash_alloc);
if (key.ifname)
@@ -152,29 +155,32 @@ static bool distribute_cmp(const struct distribute *dist1,
}
/* Set access-list name to the distribute list. */
-static void distribute_list_set(const char *ifname, enum distribute_type type,
+static void distribute_list_set(struct distribute_ctx *ctx,
+ const char *ifname, enum distribute_type type,
const char *alist_name)
{
struct distribute *dist;
- dist = distribute_get(ifname);
+ dist = distribute_get(ctx, ifname);
if (dist->list[type])
XFREE(MTYPE_DISTRIBUTE_NAME, dist->list[type]);
dist->list[type] = XSTRDUP(MTYPE_DISTRIBUTE_NAME, alist_name);
/* Apply this distribute-list to the interface. */
- (*distribute_add_hook)(dist);
+ (ctx->distribute_add_hook)(ctx, dist);
}
/* Unset distribute-list. If matched distribute-list exist then
return 1. */
-static int distribute_list_unset(const char *ifname, enum distribute_type type,
+static int distribute_list_unset(struct distribute_ctx *ctx,
+ const char *ifname,
+ enum distribute_type type,
const char *alist_name)
{
struct distribute *dist;
- dist = distribute_lookup(ifname);
+ dist = distribute_lookup(ctx, ifname);
if (!dist)
return 0;
@@ -187,39 +193,41 @@ static int distribute_list_unset(const char *ifname, enum distribute_type type,
dist->list[type] = NULL;
/* Apply this distribute-list to the interface. */
- (*distribute_delete_hook)(dist);
+ (ctx->distribute_delete_hook)(ctx, dist);
/* If all dist are NULL, then free distribute list. */
- distribute_free_if_empty(dist);
+ distribute_free_if_empty(ctx, dist);
return 1;
}
/* Set access-list name to the distribute list. */
-static void distribute_list_prefix_set(const char *ifname,
+static void distribute_list_prefix_set(struct distribute_ctx *ctx,
+ const char *ifname,
enum distribute_type type,
const char *plist_name)
{
struct distribute *dist;
- dist = distribute_get(ifname);
+ dist = distribute_get(ctx, ifname);
if (dist->prefix[type])
XFREE(MTYPE_DISTRIBUTE_NAME, dist->prefix[type]);
dist->prefix[type] = XSTRDUP(MTYPE_DISTRIBUTE_NAME, plist_name);
/* Apply this distribute-list to the interface. */
- (*distribute_add_hook)(dist);
+ (ctx->distribute_add_hook)(ctx, dist);
}
/* Unset distribute-list. If matched distribute-list exist then
return 1. */
-static int distribute_list_prefix_unset(const char *ifname,
+static int distribute_list_prefix_unset(struct distribute_ctx *ctx,
+ const char *ifname,
enum distribute_type type,
const char *plist_name)
{
struct distribute *dist;
- dist = distribute_lookup(ifname);
+ dist = distribute_lookup(ctx, ifname);
if (!dist)
return 0;
@@ -232,10 +240,10 @@ static int distribute_list_prefix_unset(const char *ifname,
dist->prefix[type] = NULL;
/* Apply this distribute-list to the interface. */
- (*distribute_delete_hook)(dist);
+ (ctx->distribute_delete_hook)(ctx, dist);
/* If all dist are NULL, then free distribute list. */
- distribute_free_if_empty(dist);
+ distribute_free_if_empty(ctx, dist);
return 1;
}
@@ -250,15 +258,17 @@ DEFUN (distribute_list,
"Interface name\n")
{
int prefix = (argv[1]->type == WORD_TKN) ? 1 : 0;
-
/* Check of distribute list type. */
enum distribute_type type = argv[2 + prefix]->arg[0] == 'i'
? DISTRIBUTE_V4_IN
: DISTRIBUTE_V4_OUT;
/* Set appropriate function call */
- void (*distfn)(const char *, enum distribute_type, const char *) =
+ void (*distfn)(struct distribute_ctx *, const char *,
+ enum distribute_type, const char *) =
prefix ? &distribute_list_prefix_set : &distribute_list_set;
+ struct distribute_ctx *ctx =
+ (struct distribute_ctx *)listnode_head(dist_ctx_list);
/* if interface is present, get name */
const char *ifname = NULL;
@@ -266,7 +276,7 @@ DEFUN (distribute_list,
ifname = argv[argc - 1]->arg;
/* Get interface name corresponding distribute list. */
- distfn(ifname, type, argv[1 + prefix]->arg);
+ distfn(ctx, ifname, type, argv[1 + prefix]->arg);
return CMD_SUCCESS;
}
@@ -283,15 +293,16 @@ DEFUN (ipv6_distribute_list,
"Interface name\n")
{
int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0;
-
/* Check of distribute list type. */
enum distribute_type type = argv[3 + prefix]->arg[0] == 'i'
? DISTRIBUTE_V6_IN
: DISTRIBUTE_V6_OUT;
/* Set appropriate function call */
- void (*distfn)(const char *, enum distribute_type, const char *) =
+ void (*distfn)(struct distribute_ctx *, const char *,
+ enum distribute_type, const char *) =
prefix ? &distribute_list_prefix_set : &distribute_list_set;
+ struct distribute_ctx *ctx = listnode_head(dist_ctx_list);
/* if interface is present, get name */
const char *ifname = NULL;
@@ -299,7 +310,7 @@ DEFUN (ipv6_distribute_list,
ifname = argv[argc - 1]->arg;
/* Get interface name corresponding distribute list. */
- distfn(ifname, type, argv[2 + prefix]->arg);
+ distfn(ctx, ifname, type, argv[2 + prefix]->arg);
return CMD_SUCCESS;
}
@@ -316,7 +327,6 @@ DEFUN (no_distribute_list,
"Interface name\n")
{
int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0;
-
int idx_alname = 2 + prefix;
int idx_disttype = idx_alname + 1;
enum distribute_type type =
@@ -324,16 +334,17 @@ DEFUN (no_distribute_list,
DISTRIBUTE_V4_IN : DISTRIBUTE_V4_OUT;
/* Set appropriate function call */
- int (*distfn)(const char *, enum distribute_type,
- const char *) =
+ int (*distfn)(struct distribute_ctx *, const char *,
+ enum distribute_type, const char *) =
prefix ? &distribute_list_prefix_unset : &distribute_list_unset;
+ struct distribute_ctx *ctx = listnode_head(dist_ctx_list);
/* if interface is present, get name */
const char *ifname = NULL;
if (argv[argc - 1]->type == VARIABLE_TKN)
ifname = argv[argc - 1]->arg;
/* Get interface name corresponding distribute list. */
- int ret = distfn(ifname, type, argv[2 + prefix]->arg);
+ int ret = distfn(ctx, ifname, type, argv[2 + prefix]->arg);
if (!ret) {
vty_out(vty, "distribute list doesn't exist\n");
@@ -355,16 +366,17 @@ DEFUN (no_ipv6_distribute_list,
"Interface name\n")
{
int prefix = (argv[3]->type == WORD_TKN) ? 1 : 0;
-
int idx_alname = 3 + prefix;
int idx_disttype = idx_alname + 1;
enum distribute_type type =
argv[idx_disttype]->arg[0] == 'i' ?
DISTRIBUTE_V6_IN : DISTRIBUTE_V6_OUT;
+ struct distribute_ctx *ctx = listnode_head(dist_ctx_list);
/* Set appropriate function call */
- int (*distfn)(const char *, enum distribute_type, const char *) =
+ int (*distfn)(struct distribute_ctx *, const char *,
+ enum distribute_type, const char *) =
prefix ? &distribute_list_prefix_unset : &distribute_list_unset;
/* if interface is present, get name */
@@ -373,7 +385,7 @@ DEFUN (no_ipv6_distribute_list,
if (argv[argc - 1]->type == VARIABLE_TKN)
ifname = argv[argc - 1]->arg;
/* Get interface name corresponding distribute list. */
- int ret = distfn(ifname, type, argv[3 + prefix]->arg);
+ int ret = distfn(ctx, ifname, type, argv[3 + prefix]->arg);
if (!ret) {
vty_out(vty, "distribute list doesn't exist\n");
@@ -393,7 +405,7 @@ static int distribute_print(struct vty *vty, char *tab[], int is_prefix,
return has_print;
}
-int config_show_distribute(struct vty *vty)
+int config_show_distribute(struct vty *vty, struct distribute_ctx *dist_ctxt)
{
unsigned int i;
int has_print = 0;
@@ -401,7 +413,7 @@ int config_show_distribute(struct vty *vty)
struct distribute *dist;
/* Output filter configuration. */
- dist = distribute_lookup(NULL);
+ dist = distribute_lookup(dist_ctxt, NULL);
vty_out(vty, " Outgoing update filter list for all interface is");
has_print = 0;
if (dist) {
@@ -419,8 +431,8 @@ int config_show_distribute(struct vty *vty)
else
vty_out(vty, " not set\n");
- for (i = 0; i < disthash->size; i++)
- for (mp = disthash->index[i]; mp; mp = mp->next) {
+ for (i = 0; i < dist_ctxt->disthash->size; i++)
+ for (mp = dist_ctxt->disthash->index[i]; mp; mp = mp->next) {
dist = mp->data;
if (dist->ifname) {
vty_out(vty, " %s filtered by",
@@ -447,7 +459,7 @@ int config_show_distribute(struct vty *vty)
/* Input filter configuration. */
- dist = distribute_lookup(NULL);
+ dist = distribute_lookup(dist_ctxt, NULL);
vty_out(vty, " Incoming update filter list for all interface is");
has_print = 0;
if (dist) {
@@ -465,8 +477,8 @@ int config_show_distribute(struct vty *vty)
else
vty_out(vty, " not set\n");
- for (i = 0; i < disthash->size; i++)
- for (mp = disthash->index[i]; mp; mp = mp->next) {
+ for (i = 0; i < dist_ctxt->disthash->size; i++)
+ for (mp = dist_ctxt->disthash->index[i]; mp; mp = mp->next) {
dist = mp->data;
if (dist->ifname) {
vty_out(vty, " %s filtered by",
@@ -494,7 +506,8 @@ int config_show_distribute(struct vty *vty)
}
/* Configuration write function. */
-int config_write_distribute(struct vty *vty)
+int config_write_distribute(struct vty *vty,
+ struct distribute_ctx *dist_ctxt)
{
unsigned int i;
int j;
@@ -502,8 +515,8 @@ int config_write_distribute(struct vty *vty)
struct hash_backet *mp;
int write = 0;
- for (i = 0; i < disthash->size; i++)
- for (mp = disthash->index[i]; mp; mp = mp->next) {
+ for (i = 0; i < dist_ctxt->disthash->size; i++)
+ for (mp = dist_ctxt->disthash->index[i]; mp; mp = mp->next) {
struct distribute *dist;
dist = mp->data;
@@ -543,19 +556,38 @@ int config_write_distribute(struct vty *vty)
return write;
}
-/* Clear all distribute list. */
-void distribute_list_reset()
+void distribute_list_delete(struct distribute_ctx **ctx)
{
- hash_clean(disthash, (void (*)(void *))distribute_free);
+ if ((*ctx)->disthash) {
+ hash_clean((*ctx)->disthash, (void (*)(void *))distribute_free);
+ }
+ if (!dist_ctx_list)
+ dist_ctx_list = list_new();
+ listnode_delete(dist_ctx_list, *ctx);
+ if (list_isempty(dist_ctx_list))
+ list_delete(&dist_ctx_list);
+ XFREE(MTYPE_DISTRIBUTE_CTX, (*ctx));
}
-/* Initialize distribute list related hash. */
-void distribute_list_init(int node)
+/* Initialize distribute list container */
+struct distribute_ctx *distribute_list_ctx_create(struct vrf *vrf)
{
- disthash = hash_create(
+ struct distribute_ctx *ctx;
+
+ ctx = XCALLOC(MTYPE_DISTRIBUTE_CTX, sizeof(struct distribute_ctx));
+ ctx->vrf = vrf;
+ ctx->disthash = hash_create(
distribute_hash_make,
(bool (*)(const void *, const void *))distribute_cmp, NULL);
+ if (!dist_ctx_list)
+ dist_ctx_list = list_new();
+ listnode_add(dist_ctx_list, ctx);
+ return ctx;
+}
+/* Initialize distribute list vty commands */
+void distribute_list_init(int node)
+{
/* vtysh command-extraction doesn't grok install_element(node, ) */
if (node == RIP_NODE) {
install_element(RIP_NODE, &distribute_list_cmd);
@@ -563,10 +595,7 @@ void distribute_list_init(int node)
} else if (node == RIPNG_NODE) {
install_element(RIPNG_NODE, &distribute_list_cmd);
install_element(RIPNG_NODE, &no_distribute_list_cmd);
- }
-
- /* install v6 */
- if (node == RIPNG_NODE) {
+ /* install v6 */
install_element(RIPNG_NODE, &ipv6_distribute_list_cmd);
install_element(RIPNG_NODE, &no_ipv6_distribute_list_cmd);
}
diff --git a/lib/distribute.h b/lib/distribute.h
index 35c5e0d6b6..44c699b38a 100644
--- a/lib/distribute.h
+++ b/lib/distribute.h
@@ -45,14 +45,36 @@ struct distribute {
char *prefix[DISTRIBUTE_MAX];
};
+struct distribute_ctx {
+ /* Hash of distribute list. */
+ struct hash *disthash;
+
+ /* Hook functions. */
+ void (*distribute_add_hook)(struct distribute_ctx *ctx,
+ struct distribute *dist);
+ void (*distribute_delete_hook)(struct distribute_ctx *ctx,
+ struct distribute *dist);
+
+ /* vrf information */
+ struct vrf *vrf;
+};
+
/* Prototypes for distribute-list. */
-extern void distribute_list_init(int);
-extern void distribute_list_reset(void);
-extern void distribute_list_add_hook(void (*)(struct distribute *));
-extern void distribute_list_delete_hook(void (*)(struct distribute *));
-extern struct distribute *distribute_lookup(const char *);
-extern int config_write_distribute(struct vty *);
-extern int config_show_distribute(struct vty *);
+extern void distribute_list_init(int node);
+extern struct distribute_ctx *distribute_list_ctx_create(struct vrf *vrf);
+extern void distribute_list_delete(struct distribute_ctx **ctx);
+extern void distribute_list_add_hook(struct distribute_ctx *ctx,
+ void (*)(struct distribute_ctx *ctx,
+ struct distribute *));
+extern void distribute_list_delete_hook(struct distribute_ctx *ctx,
+ void (*)(struct distribute_ctx *ctx,
+ struct distribute *));
+extern struct distribute *distribute_lookup(struct distribute_ctx *ctx,
+ const char *ifname);
+extern int config_write_distribute(struct vty *vty,
+ struct distribute_ctx *ctx);
+extern int config_show_distribute(struct vty *vty,
+ struct distribute_ctx *ctx);
extern enum filter_type distribute_apply_in(struct interface *,
struct prefix *);
diff --git a/lib/mlag.c b/lib/mlag.c
new file mode 100644
index 0000000000..acdc662924
--- /dev/null
+++ b/lib/mlag.c
@@ -0,0 +1,41 @@
+/* mlag generic code.
+ * Copyright (C) 2018 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.
+ */
+#include <zebra.h>
+
+#include <mlag.h>
+
+char *mlag_role2str(enum mlag_role role, char *buf, size_t size)
+{
+ switch (role) {
+ case MLAG_ROLE_NONE:
+ snprintf(buf, size, "NONE");
+ break;
+ case MLAG_ROLE_PRIMARY:
+ snprintf(buf, size, "PRIMARY");
+ break;
+ case MLAG_ROLE_SECONDARY:
+ snprintf(buf, size, "SECONDARY");
+ break;
+ }
+
+ return buf;
+}
diff --git a/lib/mlag.h b/lib/mlag.h
new file mode 100644
index 0000000000..73725ca3fd
--- /dev/null
+++ b/lib/mlag.h
@@ -0,0 +1,32 @@
+/* mlag header.
+ * Copyright (C) 2018 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 __MLAG_H__
+#define __MLAG_H__
+
+enum mlag_role {
+ MLAG_ROLE_NONE,
+ MLAG_ROLE_PRIMARY,
+ MLAG_ROLE_SECONDARY
+};
+
+extern char *mlag_role2str(enum mlag_role role, char *buf, size_t size);
+#endif
diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c
index acde0ead02..2b024ace93 100644
--- a/lib/northbound_cli.c
+++ b/lib/northbound_cli.c
@@ -79,8 +79,7 @@ void nb_cli_enqueue_change(struct vty *vty, const char *xpath,
int nb_cli_apply_changes(struct vty *vty, const char *xpath_base_fmt, ...)
{
struct nb_config *candidate_transitory;
- char xpath_base[XPATH_MAXLEN];
- va_list ap;
+ char xpath_base[XPATH_MAXLEN] = {};
bool error = false;
int ret;
@@ -94,9 +93,13 @@ int nb_cli_apply_changes(struct vty *vty, const char *xpath_base_fmt, ...)
candidate_transitory = nb_config_dup(vty->candidate_config);
/* Parse the base XPath format string. */
- va_start(ap, xpath_base_fmt);
- vsnprintf(xpath_base, sizeof(xpath_base), xpath_base_fmt, ap);
- va_end(ap);
+ if (xpath_base_fmt) {
+ va_list ap;
+
+ va_start(ap, xpath_base_fmt);
+ vsnprintf(xpath_base, sizeof(xpath_base), xpath_base_fmt, ap);
+ va_end(ap);
+ }
/* Edit candidate configuration. */
for (size_t i = 0; i < vty->num_cfg_changes; i++) {
diff --git a/lib/northbound_cli.h b/lib/northbound_cli.h
index 362a4bc325..884f250941 100644
--- a/lib/northbound_cli.h
+++ b/lib/northbound_cli.h
@@ -60,7 +60,7 @@ extern void nb_cli_enqueue_change(struct vty *vty, const char *xpath,
*
* xpath_base_fmt
* Prepend the given XPath (absolute or relative) to all enqueued
- * configuration changes.
+ * configuration changes. This is an optional parameter.
*
* Returns:
* CMD_SUCCESS on success, CMD_WARNING_CONFIG_FAILED otherwise.
diff --git a/lib/subdir.am b/lib/subdir.am
index 43b39100cb..ccbe13bca6 100644
--- a/lib/subdir.am
+++ b/lib/subdir.am
@@ -44,6 +44,7 @@ lib_libfrr_la_SOURCES = \
lib/md5.c \
lib/memory.c \
lib/memory_vty.c \
+ lib/mlag.c \
lib/module.c \
lib/mpls.c \
lib/network.c \
@@ -134,6 +135,7 @@ pkginclude_HEADERS += \
lib/bitfield.h \
lib/buffer.h \
lib/checksum.h \
+ lib/mlag.h \
lib/command.h \
lib/command_graph.h \
lib/command_match.h \
diff --git a/lib/vrf.c b/lib/vrf.c
index 8409a1c9a1..0c82f6a3cd 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -330,6 +330,8 @@ vrf_id_t vrf_name_to_id(const char *name)
vrf_id_t vrf_id = VRF_DEFAULT; // Pending: need a way to return invalid
// id/ routine not used.
+ if (!name)
+ return vrf_id;
vrf = vrf_lookup_by_name(name);
if (vrf)
vrf_id = vrf->vrf_id;
diff --git a/lib/zclient.c b/lib/zclient.c
index beb3ca4f34..1c40750db0 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -1770,19 +1770,19 @@ struct interface *zebra_interface_vrf_update_read(struct stream *s,
vrf_id_t vrf_id,
vrf_id_t *new_vrf_id)
{
- unsigned int ifindex;
+ char ifname[INTERFACE_NAMSIZ];
struct interface *ifp;
vrf_id_t new_id;
- /* Get interface index. */
- ifindex = stream_getl(s);
+ /* Read interface name. */
+ stream_get(ifname, s, INTERFACE_NAMSIZ);
/* Lookup interface. */
- ifp = if_lookup_by_index(ifindex, vrf_id);
+ ifp = if_lookup_by_name(ifname, vrf_id);
if (ifp == NULL) {
flog_err(EC_LIB_ZAPI_ENCODE,
- "INTERFACE_VRF_UPDATE: Cannot find IF %u in VRF %d",
- ifindex, vrf_id);
+ "INTERFACE_VRF_UPDATE: Cannot find IF %s in VRF %d",
+ ifname, vrf_id);
return NULL;
}
@@ -2355,6 +2355,7 @@ static void zclient_capability_decode(int command, struct zclient *zclient,
STREAM_GETC(s, mpls_enabled);
cap.mpls_enabled = !!mpls_enabled;
STREAM_GETL(s, cap.ecmp);
+ STREAM_GETC(s, cap.role);
if (zclient->zebra_capabilities)
(*zclient->zebra_capabilities)(&cap);
diff --git a/lib/zclient.h b/lib/zclient.h
index 8fe711f310..831cccfb7e 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -36,6 +36,8 @@
/* For union pw_protocol_fields */
#include "pw.h"
+#include "mlag.h"
+
/* For input/output buffer to zebra. */
#define ZEBRA_MAX_PACKET_SIZ 16384
@@ -171,6 +173,7 @@ struct redist_proto {
struct zclient_capabilities {
uint32_t ecmp;
bool mpls_enabled;
+ enum mlag_role role;
};
/* Structure for the zebra client. */
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index fb08833b61..3ab9c018ea 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -5096,15 +5096,12 @@ static void show_ip_ospf_neighbor_detail_sub(struct vty *vty,
}
static int show_ip_ospf_neighbor_id_common(struct vty *vty, struct ospf *ospf,
- int arg_base,
- struct cmd_token **argv,
+ struct in_addr *router_id,
bool use_json, uint8_t use_vrf)
{
struct listnode *node;
struct ospf_neighbor *nbr;
struct ospf_interface *oi;
- struct in_addr router_id;
- int ret;
json_object *json = NULL;
if (use_json)
@@ -5120,19 +5117,8 @@ static int show_ip_ospf_neighbor_id_common(struct vty *vty, struct ospf *ospf,
ospf_show_vrf_name(ospf, vty, json, use_vrf);
- ret = inet_aton(argv[arg_base]->arg, &router_id);
- if (!ret) {
- if (!use_json)
- vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n");
- else {
- vty_out(vty, "{}\n");
- json_object_free(json);
- }
- return CMD_WARNING;
- }
-
for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
- if ((nbr = ospf_nbr_lookup_by_routerid(oi->nbrs, &router_id))) {
+ if ((nbr = ospf_nbr_lookup_by_routerid(oi->nbrs, router_id))) {
show_ip_ospf_neighbor_detail_sub(vty, oi, nbr, json,
use_json);
}
@@ -5148,9 +5134,9 @@ static int show_ip_ospf_neighbor_id_common(struct vty *vty, struct ospf *ospf,
return CMD_SUCCESS;
}
-DEFUN (show_ip_ospf_neighbor_id,
+DEFPY (show_ip_ospf_neighbor_id,
show_ip_ospf_neighbor_id_cmd,
- "show ip ospf neighbor A.B.C.D [json]",
+ "show ip ospf neighbor A.B.C.D$router_id [json$json]",
SHOW_STR
IP_STR
"OSPF information\n"
@@ -5159,23 +5145,22 @@ DEFUN (show_ip_ospf_neighbor_id,
JSON_STR)
{
struct ospf *ospf;
- bool uj = use_json(argc, argv);
- struct listnode *node = NULL;
+ struct listnode *node;
int ret = CMD_SUCCESS;
for (ALL_LIST_ELEMENTS_RO(om->ospf, node, ospf)) {
if (!ospf->oi_running)
continue;
- ret = show_ip_ospf_neighbor_id_common(vty, ospf, 0, argv, uj,
- 0);
+ ret = show_ip_ospf_neighbor_id_common(vty, ospf, &router_id,
+ !!json, 0);
}
return ret;
}
-DEFUN (show_ip_ospf_instance_neighbor_id,
+DEFPY (show_ip_ospf_instance_neighbor_id,
show_ip_ospf_instance_neighbor_id_cmd,
- "show ip ospf (1-65535) neighbor A.B.C.D [json]",
+ "show ip ospf (1-65535)$instance neighbor A.B.C.D$router_id [json$json]",
SHOW_STR
IP_STR
"OSPF information\n"
@@ -5184,13 +5169,8 @@ DEFUN (show_ip_ospf_instance_neighbor_id,
"Neighbor ID\n"
JSON_STR)
{
- int idx_number = 3;
- int idx_router_id = 5;
struct ospf *ospf;
- unsigned short instance = 0;
- bool uj = use_json(argc, argv);
- instance = strtoul(argv[idx_number]->arg, NULL, 10);
ospf = ospf_lookup_instance(instance);
if (ospf == NULL)
return CMD_NOT_MY_INSTANCE;
@@ -5198,8 +5178,8 @@ DEFUN (show_ip_ospf_instance_neighbor_id,
if (!ospf->oi_running)
return CMD_SUCCESS;
- return show_ip_ospf_neighbor_id_common(vty, ospf, idx_router_id, argv,
- uj, 0);
+ return show_ip_ospf_neighbor_id_common(vty, ospf, &router_id, !!json,
+ 0);
}
static int show_ip_ospf_neighbor_detail_common(struct vty *vty,
diff --git a/pimd/pim_assert.c b/pimd/pim_assert.c
index 3f863ebeca..0a450834e3 100644
--- a/pimd/pim_assert.c
+++ b/pimd/pim_assert.c
@@ -569,7 +569,7 @@ static void pim_assert_timer_set(struct pim_ifchannel *ch, int interval)
ch->interface->name);
}
- thread_add_timer(master, on_assert_timer, ch, interval,
+ thread_add_timer(router->master, on_assert_timer, ch, interval,
&ch->t_ifassert_timer);
}
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 26932eea20..7089e21513 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -2646,7 +2646,7 @@ static void show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim,
if (json) {
json_object_int_add(json, "rpfCacheRefreshDelayMsecs",
- qpim_rpf_cache_refresh_delay_msec);
+ router->rpf_cache_refresh_delay_msec);
json_object_int_add(
json, "rpfCacheRefreshTimer",
pim_time_timer_remain_msec(pim->rpf_cache_refresher));
@@ -2669,7 +2669,7 @@ static void show_rpf_refresh_stats(struct vty *vty, struct pim_instance *pim,
"RPF Cache Refresh Last: %s\n"
"Nexthop Lookups: %lld\n"
"Nexthop Lookups Avoided: %lld\n",
- qpim_rpf_cache_refresh_delay_msec,
+ router->rpf_cache_refresh_delay_msec,
pim_time_timer_remain_msec(pim->rpf_cache_refresher),
(long long)pim->rpf_cache_refresh_requests,
(long long)pim->rpf_cache_refresh_events,
@@ -4408,9 +4408,12 @@ static void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim,
struct vrf *vrf = pim->vrf;
time_t now = pim_time_monotonic_sec();
char uptime[10];
+ char mlag_role[80];
pim = vrf->info;
+ vty_out(vty, "Router MLAG Role: %s\n",
+ mlag_role2str(router->role, mlag_role, sizeof(mlag_role)));
vty_out(vty, "Mroute socket descriptor:");
vty_out(vty, " %d(%s)\n", pim->mroute_socket, vrf->name);
@@ -4428,7 +4431,7 @@ static void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim,
vty_out(vty, "Maximum highest VifIndex: %d\n", PIM_MAX_USABLE_VIFS);
vty_out(vty, "\n");
- vty_out(vty, "Upstream Join Timer: %d secs\n", qpim_t_periodic);
+ vty_out(vty, "Upstream Join Timer: %d secs\n", router->t_periodic);
vty_out(vty, "Join/Prune Holdtime: %d secs\n", PIM_JP_HOLDTIME);
vty_out(vty, "PIM ECMP: %s\n", pim->ecmp_enable ? "Enable" : "Disable");
vty_out(vty, "PIM ECMP Rebalance: %s\n",
@@ -5229,7 +5232,7 @@ DEFUN (ip_pim_joinprune_time,
"Seconds\n")
{
PIM_DECLVAR_CONTEXT(vrf, pim);
- qpim_t_periodic = atoi(argv[3]->arg);
+ router->t_periodic = atoi(argv[3]->arg);
return CMD_SUCCESS;
}
@@ -5243,7 +5246,7 @@ DEFUN (no_ip_pim_joinprune_time,
"Seconds\n")
{
PIM_DECLVAR_CONTEXT(vrf, pim);
- qpim_t_periodic = PIM_DEFAULT_T_PERIODIC;
+ router->t_periodic = PIM_DEFAULT_T_PERIODIC;
return CMD_SUCCESS;
}
@@ -5256,7 +5259,7 @@ DEFUN (ip_pim_register_suppress,
"Seconds\n")
{
PIM_DECLVAR_CONTEXT(vrf, pim);
- qpim_register_suppress_time = atoi(argv[3]->arg);
+ router->register_suppress_time = atoi(argv[3]->arg);
return CMD_SUCCESS;
}
@@ -5270,7 +5273,7 @@ DEFUN (no_ip_pim_register_suppress,
"Seconds\n")
{
PIM_DECLVAR_CONTEXT(vrf, pim);
- qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT;
+ router->register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT;
return CMD_SUCCESS;
}
@@ -5339,7 +5342,7 @@ DEFUN (ip_pim_packets,
"Number of packets\n")
{
PIM_DECLVAR_CONTEXT(vrf, pim);
- qpim_packet_process = atoi(argv[3]->arg);
+ router->packet_process = atoi(argv[3]->arg);
return CMD_SUCCESS;
}
@@ -5353,7 +5356,7 @@ DEFUN (no_ip_pim_packets,
"Number of packets\n")
{
PIM_DECLVAR_CONTEXT(vrf, pim);
- qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS;
+ router->packet_process = PIM_DEFAULT_PACKET_PROCESS;
return CMD_SUCCESS;
}
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index 1ad71823b8..0451ab1e71 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -1157,7 +1157,7 @@ long pim_if_t_suppressed_msec(struct interface *ifp)
/* t_suppressed = t_periodic * rand(1.1, 1.4) */
ramount = 1100 + (random() % (1400 - 1100 + 1));
- t_suppressed_msec = qpim_t_periodic * ramount;
+ t_suppressed_msec = router->t_periodic * ramount;
return t_suppressed_msec;
}
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index 8f6a9ece53..14ce8d7d9f 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -415,7 +415,7 @@ void reset_ifassert_state(struct pim_ifchannel *ch)
THREAD_OFF(ch->t_ifassert_timer);
pim_ifassert_winner_set(ch, PIM_IFASSERT_NOINFO, any,
- qpim_infinite_assert_metric);
+ router->infinite_assert_metric);
}
struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp,
@@ -889,8 +889,8 @@ void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr,
}
if (holdtime != 0xFFFF) {
- thread_add_timer(master, on_ifjoin_expiry_timer, ch, holdtime,
- &ch->t_ifjoin_expiry_timer);
+ thread_add_timer(router->master, on_ifjoin_expiry_timer, ch,
+ holdtime, &ch->t_ifjoin_expiry_timer);
}
}
@@ -945,11 +945,12 @@ void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream,
THREAD_OFF(ch->t_ifjoin_prune_pending_timer);
THREAD_OFF(ch->t_ifjoin_expiry_timer);
thread_add_timer_msec(
- master, on_ifjoin_prune_pending_timer, ch,
- jp_override_interval_msec,
+ router->master, on_ifjoin_prune_pending_timer,
+ ch, jp_override_interval_msec,
&ch->t_ifjoin_prune_pending_timer);
- thread_add_timer(master, on_ifjoin_expiry_timer, ch,
- holdtime, &ch->t_ifjoin_expiry_timer);
+ thread_add_timer(router->master, on_ifjoin_expiry_timer,
+ ch, holdtime,
+ &ch->t_ifjoin_expiry_timer);
pim_upstream_update_join_desired(pim_ifp->pim,
ch->upstream);
}
@@ -973,31 +974,35 @@ void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream,
be taken not to use "ch" afterwards since it would be
deleted. */
THREAD_OFF(ch->t_ifjoin_prune_pending_timer);
- thread_add_timer_msec(master, on_ifjoin_prune_pending_timer, ch,
+ thread_add_timer_msec(router->master,
+ on_ifjoin_prune_pending_timer, ch,
jp_override_interval_msec,
&ch->t_ifjoin_prune_pending_timer);
break;
case PIM_IFJOIN_PRUNE:
if (source_flags & PIM_ENCODE_RPT_BIT) {
THREAD_OFF(ch->t_ifjoin_prune_pending_timer);
- thread_add_timer(master, on_ifjoin_expiry_timer, ch,
- holdtime, &ch->t_ifjoin_expiry_timer);
+ thread_add_timer(router->master, on_ifjoin_expiry_timer,
+ ch, holdtime,
+ &ch->t_ifjoin_expiry_timer);
}
break;
case PIM_IFJOIN_PRUNE_TMP:
if (source_flags & PIM_ENCODE_RPT_BIT) {
ch->ifjoin_state = PIM_IFJOIN_PRUNE;
THREAD_OFF(ch->t_ifjoin_expiry_timer);
- thread_add_timer(master, on_ifjoin_expiry_timer, ch,
- holdtime, &ch->t_ifjoin_expiry_timer);
+ thread_add_timer(router->master, on_ifjoin_expiry_timer,
+ ch, holdtime,
+ &ch->t_ifjoin_expiry_timer);
}
break;
case PIM_IFJOIN_PRUNE_PENDING_TMP:
if (source_flags & PIM_ENCODE_RPT_BIT) {
ch->ifjoin_state = PIM_IFJOIN_PRUNE_PENDING;
THREAD_OFF(ch->t_ifjoin_expiry_timer);
- thread_add_timer(master, on_ifjoin_expiry_timer, ch,
- holdtime, &ch->t_ifjoin_expiry_timer);
+ thread_add_timer(router->master, on_ifjoin_expiry_timer,
+ ch, holdtime,
+ &ch->t_ifjoin_expiry_timer);
}
break;
}
diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c
index 7a19d25a7b..cdd156b96f 100644
--- a/pimd/pim_igmp.c
+++ b/pimd/pim_igmp.c
@@ -250,8 +250,8 @@ void pim_igmp_other_querier_timer_on(struct igmp_sock *igmp)
other_querier_present_interval_msec % 1000);
}
- thread_add_timer_msec(master, pim_igmp_other_querier_expire, igmp,
- other_querier_present_interval_msec,
+ thread_add_timer_msec(router->master, pim_igmp_other_querier_expire,
+ igmp, other_querier_present_interval_msec,
&igmp->t_other_querier_timer);
}
@@ -603,8 +603,8 @@ void pim_igmp_general_query_on(struct igmp_sock *igmp)
startup_mode ? "startup" : "non-startup", igmp->fd);
}
igmp->t_igmp_query_timer = NULL;
- thread_add_timer(master, pim_igmp_general_query, igmp, query_interval,
- &igmp->t_igmp_query_timer);
+ thread_add_timer(router->master, pim_igmp_general_query, igmp,
+ query_interval, &igmp->t_igmp_query_timer);
}
void pim_igmp_general_query_off(struct igmp_sock *igmp)
@@ -940,7 +940,7 @@ static void igmp_read_on(struct igmp_sock *igmp)
igmp->fd);
}
igmp->t_igmp_read = NULL;
- thread_add_read(master, pim_igmp_read, igmp, igmp->fd,
+ thread_add_read(router->master, pim_igmp_read, igmp, igmp->fd,
&igmp->t_igmp_read);
}
@@ -1067,8 +1067,8 @@ void igmp_group_timer_on(struct igmp_group *group, long interval_msec,
*/
zassert(group->group_filtermode_isexcl);
- thread_add_timer_msec(master, igmp_group_timer, group, interval_msec,
- &group->t_group_timer);
+ thread_add_timer_msec(router->master, igmp_group_timer, group,
+ interval_msec, &group->t_group_timer);
}
struct igmp_group *find_group_by_addr(struct igmp_sock *igmp,
diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c
index 430cba76b0..b845f54f06 100644
--- a/pimd/pim_igmpv3.c
+++ b/pimd/pim_igmpv3.c
@@ -214,8 +214,8 @@ static void igmp_source_timer_on(struct igmp_group *group,
source_str, group->group_igmp_sock->interface->name);
}
- thread_add_timer_msec(master, igmp_source_timer, source, interval_msec,
- &source->t_source_timer);
+ thread_add_timer_msec(router->master, igmp_source_timer, source,
+ interval_msec, &source->t_source_timer);
/*
RFC 3376: 6.3. IGMPv3 Source-Specific Forwarding Rules
@@ -1294,7 +1294,8 @@ static void group_retransmit_timer_on(struct igmp_group *group)
igmp->interface->name);
}
- thread_add_timer_msec(master, igmp_group_retransmit, group, lmqi_msec,
+ thread_add_timer_msec(router->master, igmp_group_retransmit, group,
+ lmqi_msec,
&group->t_group_query_retransmit_timer);
}
diff --git a/pimd/pim_instance.c b/pimd/pim_instance.c
index b0d7a7b2db..092a2d76fa 100644
--- a/pimd/pim_instance.c
+++ b/pimd/pim_instance.c
@@ -85,7 +85,7 @@ static struct pim_instance *pim_instance_init(struct vrf *vrf)
pim->spt.switchover = PIM_SPT_IMMEDIATE;
pim->spt.plist = NULL;
- pim_msdp_init(pim, master);
+ pim_msdp_init(pim, router->master);
snprintf(hash_name, 64, "PIM %s RPF Hash", vrf->name);
pim->rpf_hash = hash_create_size(256, pim_rpf_hash_key, pim_rpf_equal,
@@ -101,9 +101,6 @@ static struct pim_instance *pim_instance_init(struct vrf *vrf)
pim->send_v6_secondary = 1;
- if (vrf->vrf_id == VRF_DEFAULT)
- pimg = pim;
-
pim_rp_init(pim);
pim_oil_init(pim);
@@ -132,9 +129,6 @@ static int pim_vrf_new(struct vrf *vrf)
vrf->info = (void *)pim;
- if (vrf->vrf_id == VRF_DEFAULT)
- pimg = pim;
-
pim_ssmpingd_init(pim);
return 0;
}
diff --git a/pimd/pim_instance.h b/pimd/pim_instance.h
index b447075e9a..e651356bfe 100644
--- a/pimd/pim_instance.h
+++ b/pimd/pim_instance.h
@@ -21,8 +21,11 @@
#ifndef __PIM_INSTANCE_H__
#define __PIM_INSTANCE_H__
+#include <mlag.h>
+
#include "pim_str.h"
#include "pim_msdp.h"
+#include "pim_assert.h"
#if defined(HAVE_LINUX_MROUTE_H)
#include <linux/mroute.h>
@@ -35,13 +38,32 @@
#define MAXVIFS (256)
#endif
#endif
-extern struct pim_instance *pimg; // Pim Global Instance
enum pim_spt_switchover {
PIM_SPT_IMMEDIATE,
PIM_SPT_INFINITY,
};
+struct pim_router {
+ struct thread_master *master;
+
+ uint32_t debugs;
+
+ int t_periodic;
+ struct pim_assert_metric infinite_assert_metric;
+ long rpf_cache_refresh_delay_msec;
+ int32_t register_suppress_time;
+ int packet_process;
+ int32_t register_probe_time;
+
+ /*
+ * What is the default vrf that we work in
+ */
+ vrf_id_t vrf_id;
+
+ enum mlag_role role;
+};
+
/* Per VRF PIM DB */
struct pim_instance {
vrf_id_t vrf_id;
diff --git a/pimd/pim_macro.c b/pimd/pim_macro.c
index 13f4240dba..908026ab14 100644
--- a/pimd/pim_macro.c
+++ b/pimd/pim_macro.c
@@ -295,7 +295,7 @@ pim_macro_ch_my_assert_metric_eval(const struct pim_ifchannel *ch)
}
}
- return qpim_infinite_assert_metric;
+ return router->infinite_assert_metric;
}
/*
diff --git a/pimd/pim_main.c b/pimd/pim_main.c
index 50ebc4003e..dc42899c7b 100644
--- a/pimd/pim_main.c
+++ b/pimd/pim_main.c
@@ -109,7 +109,7 @@ int main(int argc, char **argv, char **envp)
}
}
- master = frr_init();
+ pim_router_init();
/*
* Initializations
@@ -157,7 +157,7 @@ int main(int argc, char **argv, char **envp)
"PIM_UNEXPECTED_KERNEL_UPCALL: report unexpected kernel upcall");
#endif
- frr_run(master);
+ frr_run(router->master);
/* never reached */
return 0;
diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c
index dc4c4402a1..dd9e21cae8 100644
--- a/pimd/pim_mroute.c
+++ b/pimd/pim_mroute.c
@@ -708,7 +708,7 @@ static int mroute_read(struct thread *t)
result = pim_mroute_msg(pim, buf, rd, ifindex);
count++;
- if (count % qpim_packet_process == 0)
+ if (count % router->packet_process == 0)
cont = 0;
}
/* Keep reading */
@@ -720,7 +720,7 @@ done:
static void mroute_read_on(struct pim_instance *pim)
{
- thread_add_read(master, mroute_read, pim, pim->mroute_socket,
+ thread_add_read(router->master, mroute_read, pim, pim->mroute_socket,
&pim->thread);
}
diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c
index 7e072e6ade..a4f87fa1a6 100644
--- a/pimd/pim_msdp.c
+++ b/pimd/pim_msdp.c
@@ -1523,8 +1523,8 @@ enum pim_msdp_err pim_msdp_mg_src_add(struct pim_instance *pim,
}
/*********************** MSDP feature APIs *********************************/
-int pim_msdp_config_write_helper(struct pim_instance *pim, struct vty *vty,
- const char *spaces)
+int pim_msdp_config_write(struct pim_instance *pim, struct vty *vty,
+ const char *spaces)
{
struct listnode *mbrnode;
struct pim_msdp_mg_mbr *mbr;
@@ -1553,11 +1553,6 @@ int pim_msdp_config_write_helper(struct pim_instance *pim, struct vty *vty,
return count;
}
-int pim_msdp_config_write(struct vty *vty)
-{
- return pim_msdp_config_write_helper(pimg, vty, "");
-}
-
/* Enable feature including active/periodic timers etc. on the first peer
* config. Till then MSDP should just stay quiet. */
static void pim_msdp_enable(struct pim_instance *pim)
diff --git a/pimd/pim_msdp.h b/pimd/pim_msdp.h
index 8363d50991..6caa3181e7 100644
--- a/pimd/pim_msdp.h
+++ b/pimd/pim_msdp.h
@@ -232,9 +232,8 @@ void pim_msdp_peer_reset_tcp_conn(struct pim_msdp_peer *mp, const char *rc_str);
int pim_msdp_write(struct thread *thread);
char *pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size,
bool long_format);
-int pim_msdp_config_write(struct vty *vty);
-int pim_msdp_config_write_helper(struct pim_instance *pim, struct vty *vty,
- const char *spaces);
+int pim_msdp_config_write(struct pim_instance *pim, struct vty *vty,
+ const char *spaces);
void pim_msdp_peer_pkt_txed(struct pim_msdp_peer *mp);
void pim_msdp_sa_ref(struct pim_instance *pim, struct pim_msdp_peer *mp,
struct prefix_sg *sg, struct in_addr rp);
diff --git a/pimd/pim_msdp_socket.c b/pimd/pim_msdp_socket.c
index 7997d3138a..b1f7cfd2c6 100644
--- a/pimd/pim_msdp_socket.c
+++ b/pimd/pim_msdp_socket.c
@@ -79,7 +79,7 @@ static int pim_msdp_sock_accept(struct thread *thread)
return -1;
}
pim->msdp.listener.thread = NULL;
- thread_add_read(master, pim_msdp_sock_accept, pim, accept_sock,
+ thread_add_read(router->master, pim_msdp_sock_accept, pim, accept_sock,
&pim->msdp.listener.thread);
/* accept client connection. */
diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c
index f402629653..436f2dec27 100644
--- a/pimd/pim_neighbor.c
+++ b/pimd/pim_neighbor.c
@@ -255,8 +255,8 @@ void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime)
neigh->interface->name);
}
- thread_add_timer(master, on_neighbor_timer, neigh, neigh->holdtime,
- &neigh->t_expire_timer);
+ thread_add_timer(router->master, on_neighbor_timer, neigh,
+ neigh->holdtime, &neigh->t_expire_timer);
}
static int on_neighbor_jp_timer(struct thread *t)
@@ -277,8 +277,8 @@ static int on_neighbor_jp_timer(struct thread *t)
rpf.rpf_addr.u.prefix4 = neigh->source_addr;
pim_joinprune_send(&rpf, neigh->upstream_jp_agg);
- thread_add_timer(master, on_neighbor_jp_timer, neigh, qpim_t_periodic,
- &neigh->jp_timer);
+ thread_add_timer(router->master, on_neighbor_jp_timer, neigh,
+ router->t_periodic, &neigh->jp_timer);
return 0;
}
@@ -286,8 +286,8 @@ static int on_neighbor_jp_timer(struct thread *t)
static void pim_neighbor_start_jp_timer(struct pim_neighbor *neigh)
{
THREAD_TIMER_OFF(neigh->jp_timer);
- thread_add_timer(master, on_neighbor_jp_timer, neigh, qpim_t_periodic,
- &neigh->jp_timer);
+ thread_add_timer(router->master, on_neighbor_jp_timer, neigh,
+ router->t_periodic, &neigh->jp_timer);
}
static struct pim_neighbor *
diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c
index 0696a680e7..71b0d47928 100644
--- a/pimd/pim_pim.c
+++ b/pimd/pim_pim.c
@@ -346,7 +346,7 @@ static int pim_sock_read(struct thread *t)
}
count++;
- if (count % qpim_packet_process == 0)
+ if (count % router->packet_process == 0)
cont = 0;
}
@@ -376,8 +376,8 @@ static void pim_sock_read_on(struct interface *ifp)
pim_ifp->pim_sock_fd);
}
pim_ifp->t_pim_sock_read = NULL;
- thread_add_read(master, pim_sock_read, ifp, pim_ifp->pim_sock_fd,
- &pim_ifp->t_pim_sock_read);
+ thread_add_read(router->master, pim_sock_read, ifp,
+ pim_ifp->pim_sock_fd, &pim_ifp->t_pim_sock_read);
}
static int pim_sock_open(struct interface *ifp)
@@ -683,7 +683,7 @@ static void hello_resched(struct interface *ifp)
pim_ifp->pim_hello_period, ifp->name);
}
THREAD_OFF(pim_ifp->t_pim_hello_timer);
- thread_add_timer(master, on_pim_hello_send, ifp,
+ thread_add_timer(router->master, on_pim_hello_send, ifp,
pim_ifp->pim_hello_period,
&pim_ifp->t_pim_hello_timer);
}
@@ -796,8 +796,8 @@ void pim_hello_restart_triggered(struct interface *ifp)
random_msec, ifp->name);
}
- thread_add_timer_msec(master, on_pim_hello_send, ifp, random_msec,
- &pim_ifp->t_pim_hello_timer);
+ thread_add_timer_msec(router->master, on_pim_hello_send, ifp,
+ random_msec, &pim_ifp->t_pim_hello_timer);
}
int pim_sock_add(struct interface *ifp)
diff --git a/pimd/pim_ssmpingd.c b/pimd/pim_ssmpingd.c
index c3d958428c..17bc375c12 100644
--- a/pimd/pim_ssmpingd.c
+++ b/pimd/pim_ssmpingd.c
@@ -339,7 +339,7 @@ static int ssmpingd_sock_read(struct thread *t)
static void ssmpingd_read_on(struct ssmpingd_sock *ss)
{
- thread_add_read(master, ssmpingd_sock_read, ss, ss->sock_fd,
+ thread_add_read(router->master, ssmpingd_sock_read, ss, ss->sock_fd,
&ss->t_sock_read);
}
diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c
index cd5b632ded..c6ab8f5a2a 100644
--- a/pimd/pim_upstream.c
+++ b/pimd/pim_upstream.c
@@ -308,7 +308,7 @@ void join_timer_start(struct pim_upstream *up)
if (PIM_DEBUG_PIM_EVENTS) {
zlog_debug(
"%s: starting %d sec timer for upstream (S,G)=%s",
- __PRETTY_FUNCTION__, qpim_t_periodic,
+ __PRETTY_FUNCTION__, router->t_periodic,
up->sg_str);
}
}
@@ -317,8 +317,8 @@ void join_timer_start(struct pim_upstream *up)
pim_jp_agg_add_group(nbr->upstream_jp_agg, up, 1);
else {
THREAD_OFF(up->t_join_timer);
- thread_add_timer(master, on_join_timer, up, qpim_t_periodic,
- &up->t_join_timer);
+ thread_add_timer(router->master, on_join_timer, up,
+ router->t_periodic, &up->t_join_timer);
}
pim_jp_agg_upstream_verification(up, true);
}
@@ -346,7 +346,7 @@ static void pim_upstream_join_timer_restart_msec(struct pim_upstream *up,
}
THREAD_OFF(up->t_join_timer);
- thread_add_timer_msec(master, on_join_timer, up, interval_msec,
+ thread_add_timer_msec(router->master, on_join_timer, up, interval_msec,
&up->t_join_timer);
}
@@ -647,9 +647,9 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4.s_addr =
PIM_NET_INADDR_ANY;
up->rpf.source_nexthop.mrib_metric_preference =
- qpim_infinite_assert_metric.metric_preference;
+ router->infinite_assert_metric.metric_preference;
up->rpf.source_nexthop.mrib_route_metric =
- qpim_infinite_assert_metric.route_metric;
+ router->infinite_assert_metric.route_metric;
up->rpf.rpf_addr.family = AF_INET;
up->rpf.rpf_addr.u.prefix4.s_addr = PIM_NET_INADDR_ANY;
@@ -1124,8 +1124,8 @@ void pim_upstream_keep_alive_timer_start(struct pim_upstream *up, uint32_t time)
up->sg_str);
}
THREAD_OFF(up->t_ka_timer);
- thread_add_timer(master, pim_upstream_keep_alive_timer, up, time,
- &up->t_ka_timer);
+ thread_add_timer(router->master, pim_upstream_keep_alive_timer, up,
+ time, &up->t_ka_timer);
/* any time keepalive is started against a SG we will have to
* re-evaluate our active source database */
@@ -1145,7 +1145,7 @@ static int pim_upstream_msdp_reg_timer(struct thread *t)
void pim_upstream_msdp_reg_timer_start(struct pim_upstream *up)
{
THREAD_OFF(up->t_msdp_reg_timer);
- thread_add_timer(master, pim_upstream_msdp_reg_timer, up,
+ thread_add_timer(router->master, pim_upstream_msdp_reg_timer, up,
PIM_MSDP_REG_RXED_PERIOD, &up->t_msdp_reg_timer);
pim_msdp_sa_local_update(up);
@@ -1406,8 +1406,8 @@ void pim_upstream_start_register_stop_timer(struct pim_upstream *up,
"%s: (S,G)=%s Starting upstream register stop timer %d",
__PRETTY_FUNCTION__, up->sg_str, time);
}
- thread_add_timer(master, pim_upstream_register_stop_timer, up, time,
- &up->t_rs_timer);
+ thread_add_timer(router->master, pim_upstream_register_stop_timer, up,
+ time, &up->t_rs_timer);
}
int pim_upstream_inherited_olist_decide(struct pim_instance *pim,
@@ -1768,7 +1768,7 @@ void pim_upstream_init(struct pim_instance *pim)
snprintf(name, 64, "PIM %s Timer Wheel",
pim->vrf->name);
pim->upstream_sg_wheel =
- wheel_init(master, 31000, 100, pim_upstream_hash_key,
+ wheel_init(router->master, 31000, 100, pim_upstream_hash_key,
pim_upstream_sg_running, name);
snprintf(name, 64, "PIM %s Upstream Hash",
diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h
index a347ab991c..f44b95c811 100644
--- a/pimd/pim_upstream.h
+++ b/pimd/pim_upstream.h
@@ -126,13 +126,14 @@ struct pim_upstream {
*/
struct thread *t_ka_timer;
#define PIM_KEEPALIVE_PERIOD (210)
-#define PIM_RP_KEEPALIVE_PERIOD ( 3 * qpim_register_suppress_time + qpim_register_probe_time )
+#define PIM_RP_KEEPALIVE_PERIOD \
+ (3 * router->register_suppress_time + router->register_probe_time)
/* on the RP we restart a timer to indicate if registers are being rxed
* for
* SG. This is needed by MSDP to determine its local SA cache */
struct thread *t_msdp_reg_timer;
-#define PIM_MSDP_REG_RXED_PERIOD (3 * (1.5 * qpim_register_suppress_time))
+#define PIM_MSDP_REG_RXED_PERIOD (3 * (1.5 * router->register_suppress_time))
int64_t state_transition; /* Record current state uptime */
};
diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c
index a4aec710e9..f6385a0ac9 100644
--- a/pimd/pim_vty.c
+++ b/pimd/pim_vty.c
@@ -163,7 +163,7 @@ int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty)
else
sprintf(spaces, "%s", " ");
- writes += pim_msdp_config_write_helper(pim, vty, spaces);
+ writes += pim_msdp_config_write(pim, vty, spaces);
if (!pim->send_v6_secondary) {
vty_out(vty, "%sno ip pim send-v6-secondary\n", spaces);
@@ -172,15 +172,15 @@ int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty)
writes += pim_rp_config_write(pim, vty, spaces);
- if (qpim_register_suppress_time
+ if (router->register_suppress_time
!= PIM_REGISTER_SUPPRESSION_TIME_DEFAULT) {
vty_out(vty, "%sip pim register-suppress-time %d\n", spaces,
- qpim_register_suppress_time);
+ router->register_suppress_time);
++writes;
}
- if (qpim_t_periodic != PIM_DEFAULT_T_PERIODIC) {
+ if (router->t_periodic != PIM_DEFAULT_T_PERIODIC) {
vty_out(vty, "%sip pim join-prune-interval %d\n", spaces,
- qpim_t_periodic);
+ router->t_periodic);
++writes;
}
if (pim->keep_alive_time != PIM_KEEPALIVE_PERIOD) {
@@ -193,9 +193,9 @@ int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty)
pim->rp_keep_alive_time);
++writes;
}
- if (qpim_packet_process != PIM_DEFAULT_PACKET_PROCESS) {
+ if (router->packet_process != PIM_DEFAULT_PACKET_PROCESS) {
vty_out(vty, "%sip pim packets %d\n", spaces,
- qpim_packet_process);
+ router->packet_process);
++writes;
}
if (ssm->plist_name) {
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index 10ea17cf1f..b7111cf7bf 100644
--- a/pimd/pim_zebra.c
+++ b/pimd/pim_zebra.c
@@ -727,11 +727,11 @@ void sched_rpf_cache_refresh(struct pim_instance *pim)
if (PIM_DEBUG_ZEBRA) {
zlog_debug("%s: triggering %ld msec timer", __PRETTY_FUNCTION__,
- qpim_rpf_cache_refresh_delay_msec);
+ router->rpf_cache_refresh_delay_msec);
}
- thread_add_timer_msec(master, on_rpf_cache_refresh, pim,
- qpim_rpf_cache_refresh_delay_msec,
+ thread_add_timer_msec(router->master, on_rpf_cache_refresh, pim,
+ router->rpf_cache_refresh_delay_msec,
&pim->rpf_cache_refresher);
}
@@ -740,14 +740,20 @@ static void pim_zebra_connected(struct zclient *zclient)
/* Send the client registration */
bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
- zclient_send_reg_requests(zclient, pimg->vrf_id);
+ zclient_send_reg_requests(zclient, router->vrf_id);
+}
+
+static void pim_zebra_capabilities(struct zclient_capabilities *cap)
+{
+ router->role = cap->role;
}
void pim_zebra_init(void)
{
/* Socket for receiving updates from Zebra daemon */
- zclient = zclient_new(master, &zclient_options_default);
+ zclient = zclient_new(router->master, &zclient_options_default);
+ zclient->zebra_capabilities = pim_zebra_capabilities;
zclient->zebra_connected = pim_zebra_connected;
zclient->router_id_update = pim_router_id_update_zebra;
zclient->interface_add = pim_zebra_if_add;
diff --git a/pimd/pim_zlookup.c b/pimd/pim_zlookup.c
index 6b45313081..0ffe313c17 100644
--- a/pimd/pim_zlookup.c
+++ b/pimd/pim_zlookup.c
@@ -71,7 +71,7 @@ static int zclient_lookup_connect(struct thread *t)
/* Schedule connection with delay. */
static void zclient_lookup_sched(struct zclient *zlookup, int delay)
{
- thread_add_timer(master, zclient_lookup_connect, zlookup, delay,
+ thread_add_timer(router->master, zclient_lookup_connect, zlookup, delay,
&zlookup->t_connect);
zlog_notice("%s: zclient lookup connection scheduled for %d seconds",
@@ -81,7 +81,7 @@ static void zclient_lookup_sched(struct zclient *zlookup, int delay)
/* Schedule connection for now. */
static void zclient_lookup_sched_now(struct zclient *zlookup)
{
- thread_add_event(master, zclient_lookup_connect, zlookup, 0,
+ thread_add_event(router->master, zclient_lookup_connect, zlookup, 0,
&zlookup->t_connect);
zlog_notice("%s: zclient lookup immediate connection scheduled",
@@ -120,7 +120,7 @@ void zclient_lookup_free(void)
void zclient_lookup_new(void)
{
- zlookup = zclient_new(master, &zclient_options_default);
+ zlookup = zclient_new(router->master, &zclient_options_default);
if (!zlookup) {
flog_err(EC_LIB_ZAPI_SOCKET, "%s: zclient_new() failure",
__PRETTY_FUNCTION__);
diff --git a/pimd/pimd.c b/pimd/pimd.c
index 5d3018b2fd..b993bcdc03 100644
--- a/pimd/pimd.c
+++ b/pimd/pimd.c
@@ -47,17 +47,9 @@ const char *const PIM_ALL_ROUTERS = MCAST_ALL_ROUTERS;
const char *const PIM_ALL_PIM_ROUTERS = MCAST_ALL_PIM_ROUTERS;
const char *const PIM_ALL_IGMP_ROUTERS = MCAST_ALL_IGMP_ROUTERS;
-struct thread_master *master = NULL;
-uint32_t qpim_debugs = 0;
-int qpim_t_periodic =
- PIM_DEFAULT_T_PERIODIC; /* Period between Join/Prune Messages */
-struct pim_assert_metric qpim_infinite_assert_metric;
-long qpim_rpf_cache_refresh_delay_msec = 50;
-int qpim_packet_process = PIM_DEFAULT_PACKET_PROCESS;
-struct pim_instance *pimg = NULL;
-
-int32_t qpim_register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT;
-int32_t qpim_register_probe_time = PIM_REGISTER_PROBE_TIME_DEFAULT;
+DEFINE_MTYPE_STATIC(PIMD, ROUTER, "PIM Router information");
+
+struct pim_router *router = NULL;
void pim_prefix_list_update(struct prefix_list *plist)
{
@@ -82,17 +74,13 @@ static void pim_free()
zclient_lookup_free();
}
-void pim_init()
+void pim_router_init(void)
{
- if (!inet_aton(PIM_ALL_PIM_ROUTERS, &qpim_all_pim_routers_addr)) {
- flog_err(
- EC_LIB_SOCKET,
- "%s %s: could not solve %s to group address: errno=%d: %s",
- __FILE__, __PRETTY_FUNCTION__, PIM_ALL_PIM_ROUTERS,
- errno, safe_strerror(errno));
- zassert(0);
- return;
- }
+ router = XCALLOC(MTYPE_ROUTER, sizeof(*router));
+
+ router->debugs = 0;
+ router->master = frr_init();
+ router->t_periodic = PIM_DEFAULT_T_PERIODIC;
/*
RFC 4601: 4.6.3. Assert Metrics
@@ -102,11 +90,35 @@ void pim_init()
return {1,infinity,infinity,0}
}
*/
- qpim_infinite_assert_metric.rpt_bit_flag = 1;
- qpim_infinite_assert_metric.metric_preference =
+ router->infinite_assert_metric.rpt_bit_flag = 1;
+ router->infinite_assert_metric.metric_preference =
PIM_ASSERT_METRIC_PREFERENCE_MAX;
- qpim_infinite_assert_metric.route_metric = PIM_ASSERT_ROUTE_METRIC_MAX;
- qpim_infinite_assert_metric.ip_address.s_addr = INADDR_ANY;
+ router->infinite_assert_metric.route_metric =
+ PIM_ASSERT_ROUTE_METRIC_MAX;
+ router->infinite_assert_metric.ip_address.s_addr = INADDR_ANY;
+ router->rpf_cache_refresh_delay_msec = 50;
+ router->register_suppress_time = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT;
+ router->packet_process = PIM_DEFAULT_PACKET_PROCESS;
+ router->register_probe_time = PIM_REGISTER_PROBE_TIME_DEFAULT;
+ router->vrf_id = VRF_DEFAULT;
+}
+
+void pim_router_terminate(void)
+{
+ XFREE(MTYPE_ROUTER, router);
+}
+
+void pim_init(void)
+{
+ if (!inet_aton(PIM_ALL_PIM_ROUTERS, &qpim_all_pim_routers_addr)) {
+ flog_err(
+ EC_LIB_SOCKET,
+ "%s %s: could not solve %s to group address: errno=%d: %s",
+ __FILE__, __PRETTY_FUNCTION__, PIM_ALL_PIM_ROUTERS,
+ errno, safe_strerror(errno));
+ zassert(0);
+ return;
+ }
pim_cmd_init();
}
@@ -130,5 +142,6 @@ void pim_terminate()
zclient_free(zclient);
}
+ pim_router_terminate();
frr_fini();
}
diff --git a/pimd/pimd.h b/pimd/pimd.h
index 1b11dc3f73..73ea9f82c4 100644
--- a/pimd/pimd.h
+++ b/pimd/pimd.h
@@ -132,110 +132,125 @@ const char *const PIM_ALL_ROUTERS;
const char *const PIM_ALL_PIM_ROUTERS;
const char *const PIM_ALL_IGMP_ROUTERS;
-extern struct thread_master *master;
+extern struct pim_router *router;
extern struct zebra_privs_t pimd_privs;
-uint32_t qpim_debugs;
struct in_addr qpim_all_pim_routers_addr;
-int qpim_t_periodic; /* Period between Join/Prune Messages */
-struct pim_assert_metric qpim_infinite_assert_metric;
-long qpim_rpf_cache_refresh_delay_msec;
-extern int qpim_packet_process;
extern uint8_t qpim_ecmp_enable;
extern uint8_t qpim_ecmp_rebalance_enable;
#define PIM_DEFAULT_PACKET_PROCESS 3
-#define PIM_JP_HOLDTIME (qpim_t_periodic * 7 / 2)
+#define PIM_JP_HOLDTIME (router->t_periodic * 7 / 2)
/*
* Register-Stop Timer (RST(S,G))
* Default values
*/
-extern int32_t qpim_register_suppress_time;
-extern int32_t qpim_register_probe_time;
#define PIM_REGISTER_SUPPRESSION_TIME_DEFAULT (60)
#define PIM_REGISTER_PROBE_TIME_DEFAULT (5)
-#define PIM_DEBUG_PIM_EVENTS (qpim_debugs & PIM_MASK_PIM_EVENTS)
-#define PIM_DEBUG_PIM_EVENTS_DETAIL (qpim_debugs & PIM_MASK_PIM_EVENTS_DETAIL)
-#define PIM_DEBUG_PIM_PACKETS (qpim_debugs & PIM_MASK_PIM_PACKETS)
-#define PIM_DEBUG_PIM_PACKETDUMP_SEND (qpim_debugs & PIM_MASK_PIM_PACKETDUMP_SEND)
-#define PIM_DEBUG_PIM_PACKETDUMP_RECV (qpim_debugs & PIM_MASK_PIM_PACKETDUMP_RECV)
-#define PIM_DEBUG_PIM_TRACE (qpim_debugs & PIM_MASK_PIM_TRACE)
-#define PIM_DEBUG_PIM_TRACE_DETAIL (qpim_debugs & PIM_MASK_PIM_TRACE_DETAIL)
-#define PIM_DEBUG_IGMP_EVENTS (qpim_debugs & PIM_MASK_IGMP_EVENTS)
-#define PIM_DEBUG_IGMP_PACKETS (qpim_debugs & PIM_MASK_IGMP_PACKETS)
-#define PIM_DEBUG_IGMP_TRACE (qpim_debugs & PIM_MASK_IGMP_TRACE)
-#define PIM_DEBUG_IGMP_TRACE_DETAIL (qpim_debugs & PIM_MASK_IGMP_TRACE_DETAIL)
-#define PIM_DEBUG_ZEBRA (qpim_debugs & PIM_MASK_ZEBRA)
-#define PIM_DEBUG_SSMPINGD (qpim_debugs & PIM_MASK_SSMPINGD)
-#define PIM_DEBUG_MROUTE (qpim_debugs & PIM_MASK_MROUTE)
-#define PIM_DEBUG_MROUTE_DETAIL (qpim_debugs & PIM_MASK_MROUTE_DETAIL)
-#define PIM_DEBUG_PIM_HELLO (qpim_debugs & PIM_MASK_PIM_HELLO)
-#define PIM_DEBUG_PIM_J_P (qpim_debugs & PIM_MASK_PIM_J_P)
-#define PIM_DEBUG_PIM_REG (qpim_debugs & PIM_MASK_PIM_REG)
-#define PIM_DEBUG_STATIC (qpim_debugs & PIM_MASK_STATIC)
-#define PIM_DEBUG_MSDP_EVENTS (qpim_debugs & PIM_MASK_MSDP_EVENTS)
-#define PIM_DEBUG_MSDP_PACKETS (qpim_debugs & PIM_MASK_MSDP_PACKETS)
-#define PIM_DEBUG_MSDP_INTERNAL (qpim_debugs & PIM_MASK_MSDP_INTERNAL)
-#define PIM_DEBUG_PIM_NHT (qpim_debugs & PIM_MASK_PIM_NHT)
-#define PIM_DEBUG_PIM_NHT_DETAIL (qpim_debugs & PIM_MASK_PIM_NHT_DETAIL)
-#define PIM_DEBUG_PIM_NHT_RP (qpim_debugs & PIM_MASK_PIM_NHT_RP)
-#define PIM_DEBUG_MTRACE (qpim_debugs & PIM_MASK_MTRACE)
-
-#define PIM_DEBUG_EVENTS (qpim_debugs & (PIM_MASK_PIM_EVENTS | PIM_MASK_IGMP_EVENTS | PIM_MASK_MSDP_EVENTS))
-#define PIM_DEBUG_PACKETS (qpim_debugs & (PIM_MASK_PIM_PACKETS | PIM_MASK_IGMP_PACKETS | PIM_MASK_MSDP_PACKETS))
-#define PIM_DEBUG_TRACE (qpim_debugs & (PIM_MASK_PIM_TRACE | PIM_MASK_IGMP_TRACE))
-
-#define PIM_DO_DEBUG_PIM_EVENTS (qpim_debugs |= PIM_MASK_PIM_EVENTS)
-#define PIM_DO_DEBUG_PIM_PACKETS (qpim_debugs |= PIM_MASK_PIM_PACKETS)
-#define PIM_DO_DEBUG_PIM_PACKETDUMP_SEND (qpim_debugs |= PIM_MASK_PIM_PACKETDUMP_SEND)
-#define PIM_DO_DEBUG_PIM_PACKETDUMP_RECV (qpim_debugs |= PIM_MASK_PIM_PACKETDUMP_RECV)
-#define PIM_DO_DEBUG_PIM_TRACE (qpim_debugs |= PIM_MASK_PIM_TRACE)
-#define PIM_DO_DEBUG_PIM_TRACE_DETAIL (qpim_debugs |= PIM_MASK_PIM_TRACE_DETAIL)
-#define PIM_DO_DEBUG_IGMP_EVENTS (qpim_debugs |= PIM_MASK_IGMP_EVENTS)
-#define PIM_DO_DEBUG_IGMP_PACKETS (qpim_debugs |= PIM_MASK_IGMP_PACKETS)
-#define PIM_DO_DEBUG_IGMP_TRACE (qpim_debugs |= PIM_MASK_IGMP_TRACE)
-#define PIM_DO_DEBUG_IGMP_TRACE_DETAIL (qpim_debugs |= PIM_MASK_IGMP_TRACE_DETAIL)
-#define PIM_DO_DEBUG_ZEBRA (qpim_debugs |= PIM_MASK_ZEBRA)
-#define PIM_DO_DEBUG_SSMPINGD (qpim_debugs |= PIM_MASK_SSMPINGD)
-#define PIM_DO_DEBUG_MROUTE (qpim_debugs |= PIM_MASK_MROUTE)
-#define PIM_DO_DEBUG_MROUTE_DETAIL (qpim_debugs |= PIM_MASK_MROUTE_DETAIL)
-#define PIM_DO_DEBUG_PIM_HELLO (qpim_debugs |= PIM_MASK_PIM_HELLO)
-#define PIM_DO_DEBUG_PIM_J_P (qpim_debugs |= PIM_MASK_PIM_J_P)
-#define PIM_DO_DEBUG_PIM_REG (qpim_debugs |= PIM_MASK_PIM_REG)
-#define PIM_DO_DEBUG_STATIC (qpim_debugs |= PIM_MASK_STATIC)
-#define PIM_DO_DEBUG_MSDP_EVENTS (qpim_debugs |= PIM_MASK_MSDP_EVENTS)
-#define PIM_DO_DEBUG_MSDP_PACKETS (qpim_debugs |= PIM_MASK_MSDP_PACKETS)
-#define PIM_DO_DEBUG_MSDP_INTERNAL (qpim_debugs |= PIM_MASK_MSDP_INTERNAL)
-#define PIM_DO_DEBUG_PIM_NHT (qpim_debugs |= PIM_MASK_PIM_NHT)
-#define PIM_DO_DEBUG_PIM_NHT_RP (qpim_debugs |= PIM_MASK_PIM_NHT_RP)
-#define PIM_DO_DEBUG_MTRACE (qpim_debugs |= PIM_MASK_MTRACE)
-
-#define PIM_DONT_DEBUG_PIM_EVENTS (qpim_debugs &= ~PIM_MASK_PIM_EVENTS)
-#define PIM_DONT_DEBUG_PIM_PACKETS (qpim_debugs &= ~PIM_MASK_PIM_PACKETS)
-#define PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND (qpim_debugs &= ~PIM_MASK_PIM_PACKETDUMP_SEND)
-#define PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV (qpim_debugs &= ~PIM_MASK_PIM_PACKETDUMP_RECV)
-#define PIM_DONT_DEBUG_PIM_TRACE (qpim_debugs &= ~PIM_MASK_PIM_TRACE)
-#define PIM_DONT_DEBUG_PIM_TRACE_DETAIL (qpim_debugs &= ~PIM_MASK_PIM_TRACE_DETAIL)
-#define PIM_DONT_DEBUG_IGMP_EVENTS (qpim_debugs &= ~PIM_MASK_IGMP_EVENTS)
-#define PIM_DONT_DEBUG_IGMP_PACKETS (qpim_debugs &= ~PIM_MASK_IGMP_PACKETS)
-#define PIM_DONT_DEBUG_IGMP_TRACE (qpim_debugs &= ~PIM_MASK_IGMP_TRACE)
-#define PIM_DONT_DEBUG_IGMP_TRACE_DETAIL (qpim_debugs &= ~PIM_MASK_IGMP_TRACE_DETAIL)
-#define PIM_DONT_DEBUG_ZEBRA (qpim_debugs &= ~PIM_MASK_ZEBRA)
-#define PIM_DONT_DEBUG_SSMPINGD (qpim_debugs &= ~PIM_MASK_SSMPINGD)
-#define PIM_DONT_DEBUG_MROUTE (qpim_debugs &= ~PIM_MASK_MROUTE)
-#define PIM_DONT_DEBUG_MROUTE_DETAIL (qpim_debugs &= ~PIM_MASK_MROUTE_DETAIL)
-#define PIM_DONT_DEBUG_PIM_HELLO (qpim_debugs &= ~PIM_MASK_PIM_HELLO)
-#define PIM_DONT_DEBUG_PIM_J_P (qpim_debugs &= ~PIM_MASK_PIM_J_P)
-#define PIM_DONT_DEBUG_PIM_REG (qpim_debugs &= ~PIM_MASK_PIM_REG)
-#define PIM_DONT_DEBUG_STATIC (qpim_debugs &= ~PIM_MASK_STATIC)
-#define PIM_DONT_DEBUG_MSDP_EVENTS (qpim_debugs &= ~PIM_MASK_MSDP_EVENTS)
-#define PIM_DONT_DEBUG_MSDP_PACKETS (qpim_debugs &= ~PIM_MASK_MSDP_PACKETS)
-#define PIM_DONT_DEBUG_MSDP_INTERNAL (qpim_debugs &= ~PIM_MASK_MSDP_INTERNAL)
-#define PIM_DONT_DEBUG_PIM_NHT (qpim_debugs &= ~PIM_MASK_PIM_NHT)
-#define PIM_DONT_DEBUG_PIM_NHT_RP (qpim_debugs &= ~PIM_MASK_PIM_NHT_RP)
-#define PIM_DONT_DEBUG_MTRACE (qpim_debugs &= ~PIM_MASK_MTRACE)
+#define PIM_DEBUG_PIM_EVENTS (router->debugs & PIM_MASK_PIM_EVENTS)
+#define PIM_DEBUG_PIM_EVENTS_DETAIL \
+ (router->debugs & PIM_MASK_PIM_EVENTS_DETAIL)
+#define PIM_DEBUG_PIM_PACKETS (router->debugs & PIM_MASK_PIM_PACKETS)
+#define PIM_DEBUG_PIM_PACKETDUMP_SEND \
+ (router->debugs & PIM_MASK_PIM_PACKETDUMP_SEND)
+#define PIM_DEBUG_PIM_PACKETDUMP_RECV \
+ (router->debugs & PIM_MASK_PIM_PACKETDUMP_RECV)
+#define PIM_DEBUG_PIM_TRACE (router->debugs & PIM_MASK_PIM_TRACE)
+#define PIM_DEBUG_PIM_TRACE_DETAIL (router->debugs & PIM_MASK_PIM_TRACE_DETAIL)
+#define PIM_DEBUG_IGMP_EVENTS (router->debugs & PIM_MASK_IGMP_EVENTS)
+#define PIM_DEBUG_IGMP_PACKETS (router->debugs & PIM_MASK_IGMP_PACKETS)
+#define PIM_DEBUG_IGMP_TRACE (router->debugs & PIM_MASK_IGMP_TRACE)
+#define PIM_DEBUG_IGMP_TRACE_DETAIL \
+ (router->debugs & PIM_MASK_IGMP_TRACE_DETAIL)
+#define PIM_DEBUG_ZEBRA (router->debugs & PIM_MASK_ZEBRA)
+#define PIM_DEBUG_SSMPINGD (router->debugs & PIM_MASK_SSMPINGD)
+#define PIM_DEBUG_MROUTE (router->debugs & PIM_MASK_MROUTE)
+#define PIM_DEBUG_MROUTE_DETAIL (router->debugs & PIM_MASK_MROUTE_DETAIL)
+#define PIM_DEBUG_PIM_HELLO (router->debugs & PIM_MASK_PIM_HELLO)
+#define PIM_DEBUG_PIM_J_P (router->debugs & PIM_MASK_PIM_J_P)
+#define PIM_DEBUG_PIM_REG (router->debugs & PIM_MASK_PIM_REG)
+#define PIM_DEBUG_STATIC (router->debugs & PIM_MASK_STATIC)
+#define PIM_DEBUG_MSDP_EVENTS (router->debugs & PIM_MASK_MSDP_EVENTS)
+#define PIM_DEBUG_MSDP_PACKETS (router->debugs & PIM_MASK_MSDP_PACKETS)
+#define PIM_DEBUG_MSDP_INTERNAL (router->debugs & PIM_MASK_MSDP_INTERNAL)
+#define PIM_DEBUG_PIM_NHT (router->debugs & PIM_MASK_PIM_NHT)
+#define PIM_DEBUG_PIM_NHT_DETAIL (router->debugs & PIM_MASK_PIM_NHT_DETAIL)
+#define PIM_DEBUG_PIM_NHT_RP (router->debugs & PIM_MASK_PIM_NHT_RP)
+#define PIM_DEBUG_MTRACE (router->debugs & PIM_MASK_MTRACE)
+
+#define PIM_DEBUG_EVENTS \
+ (router->debugs \
+ & (PIM_MASK_PIM_EVENTS | PIM_MASK_IGMP_EVENTS \
+ | PIM_MASK_MSDP_EVENTS))
+#define PIM_DEBUG_PACKETS \
+ (router->debugs \
+ & (PIM_MASK_PIM_PACKETS | PIM_MASK_IGMP_PACKETS \
+ | PIM_MASK_MSDP_PACKETS))
+#define PIM_DEBUG_TRACE \
+ (router->debugs & (PIM_MASK_PIM_TRACE | PIM_MASK_IGMP_TRACE))
+
+#define PIM_DO_DEBUG_PIM_EVENTS (router->debugs |= PIM_MASK_PIM_EVENTS)
+#define PIM_DO_DEBUG_PIM_PACKETS (router->debugs |= PIM_MASK_PIM_PACKETS)
+#define PIM_DO_DEBUG_PIM_PACKETDUMP_SEND \
+ (router->debugs |= PIM_MASK_PIM_PACKETDUMP_SEND)
+#define PIM_DO_DEBUG_PIM_PACKETDUMP_RECV \
+ (router->debugs |= PIM_MASK_PIM_PACKETDUMP_RECV)
+#define PIM_DO_DEBUG_PIM_TRACE (router->debugs |= PIM_MASK_PIM_TRACE)
+#define PIM_DO_DEBUG_PIM_TRACE_DETAIL \
+ (router->debugs |= PIM_MASK_PIM_TRACE_DETAIL)
+#define PIM_DO_DEBUG_IGMP_EVENTS (router->debugs |= PIM_MASK_IGMP_EVENTS)
+#define PIM_DO_DEBUG_IGMP_PACKETS (router->debugs |= PIM_MASK_IGMP_PACKETS)
+#define PIM_DO_DEBUG_IGMP_TRACE (router->debugs |= PIM_MASK_IGMP_TRACE)
+#define PIM_DO_DEBUG_IGMP_TRACE_DETAIL \
+ (router->debugs |= PIM_MASK_IGMP_TRACE_DETAIL)
+#define PIM_DO_DEBUG_ZEBRA (router->debugs |= PIM_MASK_ZEBRA)
+#define PIM_DO_DEBUG_SSMPINGD (router->debugs |= PIM_MASK_SSMPINGD)
+#define PIM_DO_DEBUG_MROUTE (router->debugs |= PIM_MASK_MROUTE)
+#define PIM_DO_DEBUG_MROUTE_DETAIL (router->debugs |= PIM_MASK_MROUTE_DETAIL)
+#define PIM_DO_DEBUG_PIM_HELLO (router->debugs |= PIM_MASK_PIM_HELLO)
+#define PIM_DO_DEBUG_PIM_J_P (router->debugs |= PIM_MASK_PIM_J_P)
+#define PIM_DO_DEBUG_PIM_REG (router->debugs |= PIM_MASK_PIM_REG)
+#define PIM_DO_DEBUG_STATIC (router->debugs |= PIM_MASK_STATIC)
+#define PIM_DO_DEBUG_MSDP_EVENTS (router->debugs |= PIM_MASK_MSDP_EVENTS)
+#define PIM_DO_DEBUG_MSDP_PACKETS (router->debugs |= PIM_MASK_MSDP_PACKETS)
+#define PIM_DO_DEBUG_MSDP_INTERNAL (router->debugs |= PIM_MASK_MSDP_INTERNAL)
+#define PIM_DO_DEBUG_PIM_NHT (router->debugs |= PIM_MASK_PIM_NHT)
+#define PIM_DO_DEBUG_PIM_NHT_RP (router->debugs |= PIM_MASK_PIM_NHT_RP)
+#define PIM_DO_DEBUG_MTRACE (router->debugs |= PIM_MASK_MTRACE)
+
+#define PIM_DONT_DEBUG_PIM_EVENTS (router->debugs &= ~PIM_MASK_PIM_EVENTS)
+#define PIM_DONT_DEBUG_PIM_PACKETS (router->debugs &= ~PIM_MASK_PIM_PACKETS)
+#define PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND \
+ (router->debugs &= ~PIM_MASK_PIM_PACKETDUMP_SEND)
+#define PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV \
+ (router->debugs &= ~PIM_MASK_PIM_PACKETDUMP_RECV)
+#define PIM_DONT_DEBUG_PIM_TRACE (router->debugs &= ~PIM_MASK_PIM_TRACE)
+#define PIM_DONT_DEBUG_PIM_TRACE_DETAIL \
+ (router->debugs &= ~PIM_MASK_PIM_TRACE_DETAIL)
+#define PIM_DONT_DEBUG_IGMP_EVENTS (router->debugs &= ~PIM_MASK_IGMP_EVENTS)
+#define PIM_DONT_DEBUG_IGMP_PACKETS (router->debugs &= ~PIM_MASK_IGMP_PACKETS)
+#define PIM_DONT_DEBUG_IGMP_TRACE (router->debugs &= ~PIM_MASK_IGMP_TRACE)
+#define PIM_DONT_DEBUG_IGMP_TRACE_DETAIL \
+ (router->debugs &= ~PIM_MASK_IGMP_TRACE_DETAIL)
+#define PIM_DONT_DEBUG_ZEBRA (router->debugs &= ~PIM_MASK_ZEBRA)
+#define PIM_DONT_DEBUG_SSMPINGD (router->debugs &= ~PIM_MASK_SSMPINGD)
+#define PIM_DONT_DEBUG_MROUTE (router->debugs &= ~PIM_MASK_MROUTE)
+#define PIM_DONT_DEBUG_MROUTE_DETAIL (router->debugs &= ~PIM_MASK_MROUTE_DETAIL)
+#define PIM_DONT_DEBUG_PIM_HELLO (router->debugs &= ~PIM_MASK_PIM_HELLO)
+#define PIM_DONT_DEBUG_PIM_J_P (router->debugs &= ~PIM_MASK_PIM_J_P)
+#define PIM_DONT_DEBUG_PIM_REG (router->debugs &= ~PIM_MASK_PIM_REG)
+#define PIM_DONT_DEBUG_STATIC (router->debugs &= ~PIM_MASK_STATIC)
+#define PIM_DONT_DEBUG_MSDP_EVENTS (router->debugs &= ~PIM_MASK_MSDP_EVENTS)
+#define PIM_DONT_DEBUG_MSDP_PACKETS (router->debugs &= ~PIM_MASK_MSDP_PACKETS)
+#define PIM_DONT_DEBUG_MSDP_INTERNAL (router->debugs &= ~PIM_MASK_MSDP_INTERNAL)
+#define PIM_DONT_DEBUG_PIM_NHT (router->debugs &= ~PIM_MASK_PIM_NHT)
+#define PIM_DONT_DEBUG_PIM_NHT_RP (router->debugs &= ~PIM_MASK_PIM_NHT_RP)
+#define PIM_DONT_DEBUG_MTRACE (router->debugs &= ~PIM_MASK_MTRACE)
+
+void pim_router_init(void);
+void pim_router_terminate(void);
void pim_init(void);
void pim_terminate(void);
diff --git a/ripd/ripd.c b/ripd/ripd.c
index 59a8832257..0ce5324057 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -68,6 +68,9 @@ static void rip_output_process(struct connected *, struct sockaddr_in *, int,
static int rip_triggered_update(struct thread *);
static int rip_update_jitter(unsigned long);
+static void rip_distribute_update(struct distribute_ctx *ctx,
+ struct distribute *dist);
+
/* RIP output routes type. */
enum { rip_all_route, rip_changed_route };
@@ -328,7 +331,7 @@ static int rip_filter(int rip_distribute, struct prefix_ipv4 *p,
}
/* All interface filter check. */
- dist = distribute_lookup(NULL);
+ dist = distribute_lookup(rip->distribute_ctx, NULL);
if (dist) {
if (dist->list[distribute]) {
alist = access_list_lookup(AFI_IP,
@@ -2702,7 +2705,13 @@ int rip_create(int socket)
/* Create read and timer thread. */
rip_event(RIP_READ, rip->sock);
rip_event(RIP_UPDATE_EVENT, 1);
-
+ /* Distribute list install. */
+ rip->distribute_ctx = distribute_list_ctx_create(
+ vrf_lookup_by_id(VRF_DEFAULT));
+ distribute_list_add_hook(rip->distribute_ctx,
+ rip_distribute_update);
+ distribute_list_delete_hook(rip->distribute_ctx,
+ rip_distribute_update);
return 0;
}
@@ -3121,7 +3130,7 @@ DEFUN (show_ip_rip_status,
vty_out(vty, " garbage collect after %u seconds\n", rip->garbage_time);
/* Filtering status show. */
- config_show_distribute(vty);
+ config_show_distribute(vty, rip->distribute_ctx);
/* Default metric information. */
vty_out(vty, " Default redistribution metric is %u\n",
@@ -3215,7 +3224,8 @@ static int config_write_rip(struct vty *vty)
nb_cli_show_dnode_cmds(vty, dnode, false);
/* Distribute configuration. */
- write += config_write_distribute(vty);
+ write += config_write_distribute(vty,
+ rip->distribute_ctx);
/* Interface routemap configuration */
write += config_write_if_rmap(vty);
@@ -3227,7 +3237,8 @@ static int config_write_rip(struct vty *vty)
static struct cmd_node rip_node = {RIP_NODE, "%s(config-router)# ", 1};
/* Distribute-list update functions. */
-static void rip_distribute_update(struct distribute *dist)
+static void rip_distribute_update(struct distribute_ctx *ctx,
+ struct distribute *dist)
{
struct interface *ifp;
struct rip_interface *ri;
@@ -3288,9 +3299,11 @@ void rip_distribute_update_interface(struct interface *ifp)
{
struct distribute *dist;
- dist = distribute_lookup(ifp->name);
+ if (!rip)
+ return;
+ dist = distribute_lookup(rip->distribute_ctx, ifp->name);
if (dist)
- rip_distribute_update(dist);
+ rip_distribute_update(rip->distribute_ctx, dist);
}
/* Update all interface's distribute list. */
@@ -3367,6 +3380,7 @@ void rip_clean(void)
route_table_finish(rip->table);
route_table_finish(rip->neighbor);
+ distribute_list_delete(&rip->distribute_ctx);
XFREE(MTYPE_RIP, rip);
rip = NULL;
}
@@ -3390,7 +3404,6 @@ static void rip_if_rmap_update(struct if_rmap *if_rmap)
return;
ri = ifp->info;
-
if (if_rmap->routemap[IF_RMAP_IN]) {
rmap = route_map_lookup_by_name(if_rmap->routemap[IF_RMAP_IN]);
if (rmap)
@@ -3472,8 +3485,6 @@ void rip_init(void)
/* Distribute list install. */
distribute_list_init(RIP_NODE);
- distribute_list_add_hook(rip_distribute_update);
- distribute_list_delete_hook(rip_distribute_update);
/* Route-map */
rip_route_map_init();
diff --git a/ripd/ripd.h b/ripd/ripd.h
index 91fab2a7a2..7b8fe3a906 100644
--- a/ripd/ripd.h
+++ b/ripd/ripd.h
@@ -23,6 +23,7 @@
#include "hook.h"
#include "nexthop.h"
+#include "distribute.h"
#include "rip_memory.h"
/* RIP version number. */
@@ -150,6 +151,9 @@ struct rip {
bool metric_config;
uint8_t metric;
} route_map[ZEBRA_ROUTE_MAX];
+
+ /* For distribute-list container */
+ struct distribute_ctx *distribute_ctx;
};
/* RIP routing table entry which belong to rip_packet. */
diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c
index 4ec9209da7..ae8e8ab7d9 100644
--- a/ripngd/ripngd.c
+++ b/ripngd/ripngd.c
@@ -52,6 +52,9 @@ enum { ripng_all_route,
ripng_changed_route,
};
+static void ripng_distribute_update(struct distribute_ctx *ctx,
+ struct distribute *dist);
+
/* Prototypes. */
void ripng_output_process(struct interface *, struct sockaddr_in6 *, int);
@@ -619,7 +622,7 @@ static int ripng_filter(int ripng_distribute, struct prefix_ipv6 *p,
}
/* All interface filter check. */
- dist = distribute_lookup(NULL);
+ dist = distribute_lookup(ripng->distribute_ctx, NULL);
if (dist) {
if (dist->list[distribute]) {
alist = access_list_lookup(AFI_IP6,
@@ -1806,6 +1809,13 @@ int ripng_create(int socket)
/* Initialize RIPng routig table. */
ripng->table = agg_table_init();
+ /* Distribute list install. */
+ ripng->distribute_ctx = distribute_list_ctx_create(
+ vrf_lookup_by_id(VRF_DEFAULT));
+ distribute_list_add_hook(ripng->distribute_ctx,
+ ripng_distribute_update);
+ distribute_list_delete_hook(ripng->distribute_ctx,
+ ripng_distribute_update);
/* Make socket. */
ripng->sock = socket;
@@ -2071,7 +2081,7 @@ DEFUN (show_ipv6_ripng_status,
ripng->garbage_time);
/* Filtering status show. */
- config_show_distribute(vty);
+ config_show_distribute(vty, ripng->distribute_ctx);
/* Default metric information. */
vty_out(vty, " Default redistribution metric is %d\n",
@@ -2290,7 +2300,8 @@ static int ripng_config_write(struct vty *vty)
if (dnode) {
nb_cli_show_dnode_cmds(vty, dnode, false);
- config_write_distribute(vty);
+ config_write_distribute(vty,
+ ripng->distribute_ctx);
config_write_if_rmap(vty);
@@ -2305,7 +2316,8 @@ static struct cmd_node cmd_ripng_node = {
RIPNG_NODE, "%s(config-router)# ", 1,
};
-static void ripng_distribute_update(struct distribute *dist)
+static void ripng_distribute_update(struct distribute_ctx *ctx,
+ struct distribute *dist)
{
struct interface *ifp;
struct ripng_interface *ri;
@@ -2366,9 +2378,11 @@ void ripng_distribute_update_interface(struct interface *ifp)
{
struct distribute *dist;
- dist = distribute_lookup(ifp->name);
+ if (!ripng)
+ return;
+ dist = distribute_lookup(ripng->distribute_ctx, ifp->name);
if (dist)
- ripng_distribute_update(dist);
+ ripng_distribute_update(ripng->distribute_ctx, dist);
}
/* Update all interface's distribute list. */
@@ -2450,6 +2464,7 @@ void ripng_clean()
stream_free(ripng->ibuf);
stream_free(ripng->obuf);
+ distribute_list_delete(&ripng->distribute_ctx);
XFREE(MTYPE_RIPNG, ripng);
ripng = NULL;
} /* if (ripng) */
@@ -2563,8 +2578,6 @@ void ripng_init()
/* Distribute list install. */
distribute_list_init(RIPNG_NODE);
- distribute_list_add_hook(ripng_distribute_update);
- distribute_list_delete_hook(ripng_distribute_update);
/* Route-map for interface. */
ripng_route_map_init();
diff --git a/ripngd/ripngd.h b/ripngd/ripngd.h
index 5b32374ace..1db7a83b11 100644
--- a/ripngd/ripngd.h
+++ b/ripngd/ripngd.h
@@ -24,6 +24,7 @@
#include <zclient.h>
#include <vty.h>
+#include <distribute.h>
#include "ripng_memory.h"
@@ -128,6 +129,9 @@ struct ripng {
bool metric_config;
uint8_t metric;
} route_map[ZEBRA_ROUTE_MAX];
+
+ /* For distribute-list container */
+ struct distribute_ctx *distribute_ctx;
};
/* Routing table entry. */
diff --git a/sharpd/sharp_main.c b/sharpd/sharp_main.c
index 20cdd21e7d..175a276089 100644
--- a/sharpd/sharp_main.c
+++ b/sharpd/sharp_main.c
@@ -42,6 +42,7 @@
#include "distribute.h"
#include "libfrr.h"
#include "routemap.h"
+#include "nexthop_group.h"
#include "sharp_zebra.h"
#include "sharp_vty.h"
@@ -150,6 +151,7 @@ int main(int argc, char **argv, char **envp)
master = frr_init();
+ nexthop_group_init(NULL, NULL, NULL, NULL);
vrf_init(NULL, NULL, NULL, NULL, NULL);
access_list_init();
diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c
index 797e336c2d..d0a34c0f93 100644
--- a/sharpd/sharp_vty.c
+++ b/sharpd/sharp_vty.c
@@ -28,6 +28,7 @@
#include "log.h"
#include "vrf.h"
#include "zclient.h"
+#include "nexthop_group.h"
#include "sharpd/sharp_zebra.h"
#include "sharpd/sharp_vty.h"
@@ -39,6 +40,14 @@ extern uint32_t total_routes;
extern uint32_t installed_routes;
extern uint32_t removed_routes;
+uint8_t inst;
+struct prefix prefix;
+struct prefix orig_prefix;
+struct nexthop nhop;
+struct nexthop_group nhop_group;
+uint32_t rts;
+int32_t repeat;
+
DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
"sharp watch nexthop X:X::X:X$nhop",
"Sharp routing Protocol\n"
@@ -81,7 +90,7 @@ DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd,
DEFPY (install_routes,
install_routes_cmd,
- "sharp install routes A.B.C.D$start nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6> (1-1000000)$routes [instance (0-255)$instance]",
+ "sharp install routes A.B.C.D$start <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|nexthop-group NAME$nexthop_group> (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt]",
"Sharp routing Protocol\n"
"install some routes\n"
"Routes to install\n"
@@ -89,40 +98,57 @@ DEFPY (install_routes,
"Nexthop to use(Can be an IPv4 or IPv6 address)\n"
"V4 Nexthop address to use\n"
"V6 Nexthop address to use\n"
+ "Nexthop-Group to use\n"
+ "The Name of the nexthop-group\n"
"How many to create\n"
"Instance to use\n"
- "Instance\n")
+ "Instance\n"
+ "Should we repeat this command\n"
+ "How many times to repeat this command\n")
{
- int i;
- struct prefix p;
- struct nexthop nhop;
- uint32_t temp;
-
total_routes = routes;
installed_routes = 0;
- memset(&p, 0, sizeof(p));
- memset(&nhop, 0, sizeof(nhop));
-
- p.family = AF_INET;
- p.prefixlen = 32;
- p.u.prefix4 = start;
+ if (rpt >= 2)
+ repeat = rpt * 2;
+ else
+ repeat = 0;
- if (nexthop4.s_addr != INADDR_ANY) {
- nhop.gate.ipv4 = nexthop4;
- nhop.type = NEXTHOP_TYPE_IPV4;
+ memset(&prefix, 0, sizeof(prefix));
+ memset(&orig_prefix, 0, sizeof(orig_prefix));
+ memset(&nhop, 0, sizeof(nhop));
+ memset(&nhop_group, 0, sizeof(nhop_group));
+
+ prefix.family = AF_INET;
+ prefix.prefixlen = 32;
+ prefix.u.prefix4 = start;
+ orig_prefix = prefix;
+
+ if (nexthop_group) {
+ struct nexthop_group_cmd *nhgc = nhgc_find(nexthop_group);
+ if (!nhgc) {
+ vty_out(vty,
+ "Specified Nexthop Group: %s does not exist\n",
+ nexthop_group);
+ return CMD_WARNING;
+ }
+
+ nhop_group.nexthop = nhgc->nhg.nexthop;
} else {
- memcpy(&nhop.gate.ipv6, &nexthop6, IPV6_MAX_BYTELEN);
- nhop.type = NEXTHOP_TYPE_IPV6;
+ if (nexthop4.s_addr != INADDR_ANY) {
+ nhop.gate.ipv4 = nexthop4;
+ nhop.type = NEXTHOP_TYPE_IPV4;
+ } else {
+ nhop.gate.ipv6 = nexthop6;
+ nhop.type = NEXTHOP_TYPE_IPV6;
+ }
+
+ nhop_group.nexthop = &nhop;
}
- zlog_debug("Inserting %ld routes", routes);
-
- temp = ntohl(p.u.prefix4.s_addr);
- for (i = 0; i < routes; i++) {
- route_add(&p, (uint8_t)instance, &nhop);
- p.u.prefix4.s_addr = htonl(++temp);
- }
+ inst = instance;
+ rts = routes;
+ sharp_install_routes_helper(&prefix, inst, &nhop_group, rts);
return CMD_SUCCESS;
}
@@ -168,25 +194,18 @@ DEFPY (remove_routes,
"instance to use\n"
"Value of instance\n")
{
- int i;
- struct prefix p;
- uint32_t temp;
total_routes = routes;
removed_routes = 0;
- memset(&p, 0, sizeof(p));
+ memset(&prefix, 0, sizeof(prefix));
- p.family = AF_INET;
- p.prefixlen = 32;
- p.u.prefix4 = start;
+ prefix.family = AF_INET;
+ prefix.prefixlen = 32;
+ prefix.u.prefix4 = start;
- zlog_debug("Removing %ld routes", routes);
-
- temp = ntohl(p.u.prefix4.s_addr);
- for (i = 0; i < routes; i++) {
- route_delete(&p, (uint8_t)instance);
- p.u.prefix4.s_addr = htonl(++temp);
- }
+ inst = instance;
+ rts = routes;
+ sharp_remove_routes_helper(&prefix, inst, rts);
return CMD_SUCCESS;
}
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c
index f752009eb8..37591fa41f 100644
--- a/sharpd/sharp_zebra.c
+++ b/sharpd/sharp_zebra.c
@@ -34,6 +34,7 @@
#include "plist.h"
#include "log.h"
#include "nexthop.h"
+#include "nexthop_group.h"
#include "sharp_zebra.h"
@@ -131,6 +132,59 @@ static int interface_state_down(int command, struct zclient *zclient,
extern uint32_t total_routes;
extern uint32_t installed_routes;
extern uint32_t removed_routes;
+extern int32_t repeat;
+extern struct prefix orig_prefix;
+extern struct nexthop_group nhop_group;
+extern uint8_t inst;
+
+void sharp_install_routes_helper(struct prefix *p, uint8_t instance,
+ struct nexthop_group *nhg,
+ uint32_t routes)
+{
+ uint32_t temp, i;
+
+ zlog_debug("Inserting %u routes", routes);
+
+ temp = ntohl(p->u.prefix4.s_addr);
+ for (i = 0; i < routes; i++) {
+ route_add(p, (uint8_t)instance, nhg);
+ p->u.prefix4.s_addr = htonl(++temp);
+ }
+}
+
+void sharp_remove_routes_helper(struct prefix *p, uint8_t instance,
+ uint32_t routes)
+{
+ uint32_t temp, i;
+
+ zlog_debug("Removing %u routes", routes);
+
+ temp = ntohl(p->u.prefix4.s_addr);
+ for (i = 0; i < routes; i++) {
+ route_delete(p, (uint8_t)instance);
+ p->u.prefix4.s_addr = htonl(++temp);
+ }
+}
+
+static void handle_repeated(bool installed)
+{
+ struct prefix p = orig_prefix;
+ repeat--;
+
+ if (repeat <= 0)
+ return;
+
+ if (installed) {
+ removed_routes = 0;
+ sharp_remove_routes_helper(&p, inst, total_routes);
+ }
+
+ if (!installed) {
+ installed_routes = 0;
+ sharp_install_routes_helper(&p, inst, &nhop_group,
+ total_routes);
+ }
+}
static int route_notify_owner(int command, struct zclient *zclient,
zebra_size_t length, vrf_id_t vrf_id)
@@ -145,8 +199,10 @@ static int route_notify_owner(int command, struct zclient *zclient,
switch (note) {
case ZAPI_ROUTE_INSTALLED:
installed_routes++;
- if (total_routes == installed_routes)
+ if (total_routes == installed_routes) {
zlog_debug("Installed All Items");
+ handle_repeated(true);
+ }
break;
case ZAPI_ROUTE_FAIL_INSTALL:
zlog_debug("Failed install of route");
@@ -156,8 +212,10 @@ static int route_notify_owner(int command, struct zclient *zclient,
break;
case ZAPI_ROUTE_REMOVED:
removed_routes++;
- if (total_routes == removed_routes)
+ if (total_routes == removed_routes) {
zlog_debug("Removed all Items");
+ handle_repeated(false);
+ }
break;
case ZAPI_ROUTE_REMOVE_FAIL:
zlog_debug("Route removal Failure");
@@ -176,10 +234,12 @@ void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label)
zclient_send_vrf_label(zclient, vrf_id, afi, label, ZEBRA_LSP_SHARP);
}
-void route_add(struct prefix *p, uint8_t instance, struct nexthop *nh)
+void route_add(struct prefix *p, uint8_t instance, struct nexthop_group *nhg)
{
struct zapi_route api;
struct zapi_nexthop *api_nh;
+ struct nexthop *nh;
+ int i = 0;
memset(&api, 0, sizeof(api));
api.vrf_id = VRF_DEFAULT;
@@ -191,12 +251,35 @@ void route_add(struct prefix *p, uint8_t instance, struct nexthop *nh)
SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
- api_nh = &api.nexthops[0];
- api_nh->vrf_id = VRF_DEFAULT;
- api_nh->gate = nh->gate;
- api_nh->type = nh->type;
- api_nh->ifindex = nh->ifindex;
- api.nexthop_num = 1;
+ for (ALL_NEXTHOPS_PTR(nhg, nh)) {
+ api_nh = &api.nexthops[i];
+ api_nh->vrf_id = VRF_DEFAULT;
+ api_nh->type = nh->type;
+ switch (nh->type) {
+ case NEXTHOP_TYPE_IPV4:
+ api_nh->gate = nh->gate;
+ break;
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ api_nh->gate = nh->gate;
+ api_nh->ifindex = nh->ifindex;
+ break;
+ case NEXTHOP_TYPE_IFINDEX:
+ api_nh->ifindex = nh->ifindex;
+ break;
+ case NEXTHOP_TYPE_IPV6:
+ memcpy(&api_nh->gate.ipv6, &nh->gate.ipv6, 16);
+ break;
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ api_nh->ifindex = nh->ifindex;
+ memcpy(&api_nh->gate.ipv6, &nh->gate.ipv6, 16);
+ break;
+ case NEXTHOP_TYPE_BLACKHOLE:
+ api_nh->bh_type = nh->bh_type;
+ break;
+ }
+ i++;
+ }
+ api.nexthop_num = i;
zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
}
diff --git a/sharpd/sharp_zebra.h b/sharpd/sharp_zebra.h
index 58438ed01d..7326056cae 100644
--- a/sharpd/sharp_zebra.h
+++ b/sharpd/sharp_zebra.h
@@ -25,7 +25,14 @@
extern void sharp_zebra_init(void);
extern void vrf_label_add(vrf_id_t vrf_id, afi_t afi, mpls_label_t label);
-extern void route_add(struct prefix *p, uint8_t instance, struct nexthop *nh);
+extern void route_add(struct prefix *p, uint8_t instance,
+ struct nexthop_group *nhg);
extern void route_delete(struct prefix *p, uint8_t instance);
extern void sharp_zebra_nexthop_watch(struct prefix *p, bool watch);
+
+extern void sharp_install_routes_helper(struct prefix *p, uint8_t instance,
+ struct nexthop_group *nhg,
+ uint32_t routes);
+extern void sharp_remove_routes_helper(struct prefix *p, uint8_t instance,
+ uint32_t routes);
#endif
diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c
index 1e23f597b0..d6db60d3ed 100644
--- a/staticd/static_zebra.c
+++ b/staticd/static_zebra.c
@@ -154,11 +154,11 @@ static int route_notify_owner(int command, struct zclient *zclient,
uint32_t table_id;
char buf[PREFIX_STRLEN];
- prefix2str(&p, buf, sizeof(buf));
-
if (!zapi_route_notify_decode(zclient->ibuf, &p, &table_id, &note))
return -1;
+ prefix2str(&p, buf, sizeof(buf));
+
switch (note) {
case ZAPI_ROUTE_FAIL_INSTALL:
zlog_warn("%s: Route %s failed to install for table: %u",
diff --git a/tests/topotests/bgp_rfapi_basic_sanity/r1/bgpd.conf b/tests/topotests/bgp_rfapi_basic_sanity/r1/bgpd.conf
index fc301e13d7..05eac758f1 100644
--- a/tests/topotests/bgp_rfapi_basic_sanity/r1/bgpd.conf
+++ b/tests/topotests/bgp_rfapi_basic_sanity/r1/bgpd.conf
@@ -20,7 +20,7 @@ router bgp 5226
neighbor 2.2.2.2 activate
exit-address-family
!
- rfp holddown-factor 100
+ rfp holddown-factor 0
!
vnc defaults
rd auto:vn:123
diff --git a/tests/topotests/bgp_rfapi_basic_sanity/r3/bgpd.conf b/tests/topotests/bgp_rfapi_basic_sanity/r3/bgpd.conf
index 0066f65a40..67b26e3a50 100644
--- a/tests/topotests/bgp_rfapi_basic_sanity/r3/bgpd.conf
+++ b/tests/topotests/bgp_rfapi_basic_sanity/r3/bgpd.conf
@@ -18,7 +18,7 @@ router bgp 5226
neighbor 2.2.2.2 activate
exit-address-family
!
- rfp holddown-factor 100
+ rfp holddown-factor 0
!
vnc defaults
rd auto:vn:123
diff --git a/tests/topotests/bgp_rfapi_basic_sanity/r4/bgpd.conf b/tests/topotests/bgp_rfapi_basic_sanity/r4/bgpd.conf
index 67c06506b5..2ba5c74e5b 100644
--- a/tests/topotests/bgp_rfapi_basic_sanity/r4/bgpd.conf
+++ b/tests/topotests/bgp_rfapi_basic_sanity/r4/bgpd.conf
@@ -19,7 +19,7 @@ router bgp 5226
neighbor 2.2.2.2 activate
exit-address-family
!
- rfp holddown-factor 100
+ rfp holddown-factor 0
!
vnc defaults
rd auto:vn:123
diff --git a/tests/topotests/bgp_rfapi_basic_sanity_config2/r1/bgpd.conf b/tests/topotests/bgp_rfapi_basic_sanity_config2/r1/bgpd.conf
index eb8d703a35..f7f5e2ee96 100644
--- a/tests/topotests/bgp_rfapi_basic_sanity_config2/r1/bgpd.conf
+++ b/tests/topotests/bgp_rfapi_basic_sanity_config2/r1/bgpd.conf
@@ -20,7 +20,7 @@ router bgp 5226
neighbor 2.2.2.2 activate
exit-address-family
!
- rfp holddown-factor 100
+ rfp holddown-factor 0
rfp full-table-download off
!
vnc defaults
diff --git a/tests/topotests/bgp_rfapi_basic_sanity_config2/r3/bgpd.conf b/tests/topotests/bgp_rfapi_basic_sanity_config2/r3/bgpd.conf
index 61164c6948..17e351988d 100644
--- a/tests/topotests/bgp_rfapi_basic_sanity_config2/r3/bgpd.conf
+++ b/tests/topotests/bgp_rfapi_basic_sanity_config2/r3/bgpd.conf
@@ -18,7 +18,7 @@ router bgp 5226
neighbor 2.2.2.2 activate
exit-address-family
!
- rfp holddown-factor 100
+ rfp holddown-factor 0
rfp full-table-download off
!
vnc defaults
diff --git a/tests/topotests/bgp_rfapi_basic_sanity_config2/r4/bgpd.conf b/tests/topotests/bgp_rfapi_basic_sanity_config2/r4/bgpd.conf
index 4294274d3d..0b8808cb80 100644
--- a/tests/topotests/bgp_rfapi_basic_sanity_config2/r4/bgpd.conf
+++ b/tests/topotests/bgp_rfapi_basic_sanity_config2/r4/bgpd.conf
@@ -19,7 +19,7 @@ router bgp 5226
neighbor 2.2.2.2 activate
exit-address-family
!
- rfp holddown-factor 100
+ rfp holddown-factor 0
rfp full-table-download off
!
vnc defaults
diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in
index 596f01738a..2b48f1f360 100755
--- a/vtysh/extract.pl.in
+++ b/vtysh/extract.pl.in
@@ -109,7 +109,7 @@ sub scan_file {
$protocol = "VTYSH_ZEBRA";
}
elsif ($file =~ /lib\/nexthop_group\.c$/) {
- $protocol = "VTYSH_PBRD";
+ $protocol = "VTYSH_PBRD | VTYSH_SHARPD";
}
elsif ($file =~ /lib\/plist\.c$/) {
if ($defun_array[1] =~ m/ipv6/) {
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 2327f2b46d..6cf45789dd 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -2110,7 +2110,7 @@ DEFSH(VTYSH_ZEBRA, vtysh_no_logicalrouter_cmd,
"The Name Space\n"
"The file name in " NS_RUN_DIR ", or a full pathname\n")
-DEFUNSH(VTYSH_PBRD, vtysh_nexthop_group, vtysh_nexthop_group_cmd,
+DEFUNSH(VTYSH_PBRD | VTYSH_SHARPD, vtysh_nexthop_group, vtysh_nexthop_group_cmd,
"nexthop-group NAME",
"Nexthop Group configuration\n"
"Name of the Nexthop Group\n")
@@ -2119,7 +2119,8 @@ DEFUNSH(VTYSH_PBRD, vtysh_nexthop_group, vtysh_nexthop_group_cmd,
return CMD_SUCCESS;
}
-DEFSH(VTYSH_PBRD, vtysh_no_nexthop_group_cmd, "no nexthop-group NAME",
+DEFSH(VTYSH_PBRD | VTYSH_SHARPD, vtysh_no_nexthop_group_cmd,
+ "no nexthop-group NAME",
NO_STR
"Nexthop Group Configuration\n"
"Name of the Nexthop Group\n")
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index f4bd193569..4e49c1fc58 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -399,7 +399,7 @@ static int get_iflink_speed(struct interface *interface)
(char *)&ifdata);
}
if (rc < 0) {
- if (IS_ZEBRA_DEBUG_KERNEL)
+ if (errno != EOPNOTSUPP && IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
"IOCTL failure to read interface %s speed: %d %s",
ifname, errno, safe_strerror(errno));
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index afc3985854..360f596b8f 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -784,7 +784,8 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int),
if (h->nlmsg_len
< NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
- zlog_err("%s error: message truncated",
+ flog_err(EC_ZEBRA_NETLINK_LENGTH_ERROR,
+ "%s error: message truncated",
nl->name);
return -1;
}
@@ -820,14 +821,6 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int),
continue;
}
- if (h->nlmsg_len
- < NLMSG_LENGTH(sizeof(struct nlmsgerr))) {
- flog_err(EC_ZEBRA_NETLINK_LENGTH_ERROR,
- "%s error: message truncated",
- nl->name);
- return -1;
- }
-
/* Deal with errors that occur because of races
* in link handling */
if (zns->is_cmd
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index 3e46a79e96..84b06e579f 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -232,7 +232,9 @@ int dplane_routing_sock = -1;
/* Yes I'm checking ugly routing socket behavior. */
/* #define DEBUG */
+size_t _rta_get(caddr_t sap, void *destp, size_t destlen, bool checkaf);
size_t rta_get(caddr_t sap, void *dest, size_t destlen);
+size_t rta_getattr(caddr_t sap, void *destp, size_t destlen);
size_t rta_getsdlname(caddr_t sap, void *dest, short *destlen);
/* Supported address family check. */
@@ -245,9 +247,10 @@ static inline int af_check(int family)
return 0;
}
-size_t rta_get(caddr_t sap, void *destp, size_t destlen)
+size_t _rta_get(caddr_t sap, void *destp, size_t destlen, bool checkaf)
{
struct sockaddr *sa = (struct sockaddr *)sap;
+ struct sockaddr_dl *sdl;
uint8_t *dest = destp;
size_t tlen, copylen;
@@ -258,7 +261,21 @@ size_t rta_get(caddr_t sap, void *destp, size_t destlen)
copylen = tlen = SAROUNDUP(sap);
#endif /* !HAVE_STRUCT_SOCKADDR_SA_LEN */
- if (copylen > 0 && dest != NULL && af_check(sa->sa_family)) {
+ if (copylen > 0 && dest != NULL) {
+ if (checkaf && af_check(sa->sa_family) == 0)
+ return tlen;
+ /*
+ * Handle sockaddr_dl corner case:
+ * RTA_NETMASK might be AF_LINK, but it doesn't anything
+ * relevant (e.g. zeroed out fields). Check for this
+ * case and avoid warning log message.
+ */
+ if (sa->sa_family == AF_LINK) {
+ sdl = (struct sockaddr_dl *)sa;
+ if (sdl->sdl_index == 0 || sdl->sdl_nlen == 0)
+ copylen = sizeof(*sdl) - sizeof(sdl->sdl_data);
+ }
+
if (copylen > destlen) {
zlog_warn("%s: destination buffer too small (%lu vs %lu)",
__func__, copylen, destlen);
@@ -270,6 +287,16 @@ size_t rta_get(caddr_t sap, void *destp, size_t destlen)
return tlen;
}
+size_t rta_get(caddr_t sap, void *destp, size_t destlen)
+{
+ return _rta_get(sap, destp, destlen, true);
+}
+
+size_t rta_getattr(caddr_t sap, void *destp, size_t destlen)
+{
+ return _rta_get(sap, destp, destlen, false);
+}
+
size_t rta_getsdlname(caddr_t sap, void *destp, short *destlen)
{
struct sockaddr_dl *sdl = (struct sockaddr_dl *)sap;
@@ -684,7 +711,7 @@ static void ifam_read_mesg(struct ifa_msghdr *ifm, union sockunion *addr,
pnt += rta_get(pnt, &gateway, sizeof(gateway));
break;
case RTA_NETMASK:
- pnt += rta_get(pnt, mask, sizeof(*mask));
+ pnt += rta_getattr(pnt, mask, sizeof(*mask));
break;
case RTA_IFP:
pnt += rta_getsdlname(pnt, ifname, ifnlen);
@@ -742,7 +769,7 @@ static void ifam_read_mesg(struct ifa_msghdr *ifm, union sockunion *addr,
/* Assert read up end point matches to end point */
pnt = (caddr_t)ROUNDUP((size_t)pnt);
- if (pnt != end)
+ if (pnt != (caddr_t)ROUNDUP((size_t)end))
zlog_debug("ifam_read() doesn't read all socket data");
}
diff --git a/zebra/subdir.am b/zebra/subdir.am
index b8f5e0d409..23c3cd4239 100644
--- a/zebra/subdir.am
+++ b/zebra/subdir.am
@@ -10,6 +10,7 @@ vtysh_scan += \
$(top_srcdir)/zebra/interface.c \
$(top_srcdir)/zebra/router-id.c \
$(top_srcdir)/zebra/rtadv.c \
+ $(top_srcdir)/zebra/zebra_mlag.c \
$(top_srcdir)/zebra/zebra_mpls_vty.c \
$(top_srcdir)/zebra/zebra_ptm.c \
$(top_srcdir)/zebra/zebra_pw.c \
@@ -64,6 +65,7 @@ zebra_zebra_SOURCES = \
zebra/rtread_sysctl.c \
zebra/rule_netlink.c \
zebra/rule_socket.c \
+ zebra/zebra_mlag.c \
zebra/zebra_l2.c \
zebra/zebra_memory.c \
zebra/zebra_dplane.c \
@@ -93,10 +95,12 @@ zebra_zebra_SOURCES = \
zebra/zebra_errors.c \
# end
+zebra/zebra_mlag_clippy.c: $(CLIPPY_DEPS)
+zebra/zebra_mlag.$(OBJEXT): zebra/zebra_mlag_clippy.c
+
zebra/zebra_vty_clippy.c: $(CLIPPY_DEPS)
zebra/zebra_vty.$(OBJEXT): zebra/zebra_vty_clippy.c
-
zebra/zebra_routemap_clippy.c: $(CLIPPY_DEPS)
zebra/zebra_routemap.$(OBJEXT): zebra/zebra_routemap_clippy.c
@@ -119,6 +123,7 @@ noinst_HEADERS += \
zebra/rt_netlink.h \
zebra/rtadv.h \
zebra/rule_netlink.h \
+ zebra/zebra_mlag.h \
zebra/zebra_fpm_private.h \
zebra/zebra_l2.h \
zebra/zebra_dplane.h \
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 26a3cd5b42..faa0eb90e4 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -63,6 +63,7 @@
#include "zebra/table_manager.h"
#include "zebra/zapi_msg.h"
#include "zebra/zebra_errors.h"
+#include "zebra/zebra_mlag.h"
/* Encoding helpers -------------------------------------------------------- */
@@ -432,8 +433,8 @@ int zsend_interface_vrf_update(struct zserv *client, struct interface *ifp,
zclient_create_header(s, ZEBRA_INTERFACE_VRF_UPDATE, ifp->vrf_id);
- /* Fill in the ifIndex of the interface and its new VRF (id) */
- stream_putl(s, ifp->ifindex);
+ /* Fill in the name of the interface and its new VRF (id) */
+ stream_put(s, ifp->name, INTERFACE_NAMSIZ);
stream_putl(s, vrf_id);
/* Write packet size. */
@@ -1657,6 +1658,7 @@ static void zsend_capabilities(struct zserv *client, struct zebra_vrf *zvrf)
zclient_create_header(s, ZEBRA_CAPABILITIES, zvrf->vrf->vrf_id);
stream_putc(s, mpls_enabled);
stream_putl(s, multipath_num);
+ stream_putc(s, zebra_mlag_get_role());
stream_putw_at(s, 0, stream_get_endp(s));
zserv_send_message(client, s);
diff --git a/zebra/zebra_mlag.c b/zebra/zebra_mlag.c
new file mode 100644
index 0000000000..35be07c024
--- /dev/null
+++ b/zebra/zebra_mlag.c
@@ -0,0 +1,83 @@
+/* Zebra Mlag Code.
+ * Copyright (C) 2018 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.
+ */
+#include "zebra.h"
+
+#include "command.h"
+#include "hook.h"
+
+#include "zebra/zebra_mlag.h"
+
+#ifndef VTYSH_EXTRACT_PL
+#include "zebra/zebra_mlag_clippy.c"
+#endif
+
+enum mlag_role role = MLAG_ROLE_NONE;
+
+enum mlag_role zebra_mlag_get_role(void)
+{
+ return role;
+}
+
+DEFUN_HIDDEN (show_mlag,
+ show_mlag_cmd,
+ "show zebra mlag",
+ SHOW_STR
+ ZEBRA_STR
+ "The mlag role on this machine\n")
+{
+ char buf[80];
+
+ vty_out(vty, "MLag is configured to: %s\n",
+ mlag_role2str(role, buf, sizeof(buf)));
+
+ return CMD_SUCCESS;
+}
+
+DEFPY_HIDDEN (test_mlag,
+ test_mlag_cmd,
+ "test zebra mlag <none$none|primary$primary|secondary$secondary>",
+ "Test code\n"
+ ZEBRA_STR
+ "Modify the Mlag state\n"
+ "Mlag is not setup on the machine\n"
+ "Mlag is setup to be primary\n"
+ "Mlag is setup to be the secondary\n")
+{
+ if (none)
+ role = MLAG_ROLE_NONE;
+ if (primary)
+ role = MLAG_ROLE_PRIMARY;
+ if (secondary)
+ role = MLAG_ROLE_SECONDARY;
+
+ return CMD_SUCCESS;
+}
+
+void zebra_mlag_init(void)
+{
+ install_element(VIEW_NODE, &show_mlag_cmd);
+ install_element(ENABLE_NODE, &test_mlag_cmd);
+}
+
+void zebra_mlag_terminate(void)
+{
+}
diff --git a/zebra/zebra_mlag.h b/zebra/zebra_mlag.h
new file mode 100644
index 0000000000..c5c147c833
--- /dev/null
+++ b/zebra/zebra_mlag.h
@@ -0,0 +1,31 @@
+/* Zebra mlag header.
+ * Copyright (C) 2018 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 __ZEBRA_MLAG_H__
+#define __ZEBRA_MLAG_H__
+
+#include "mlag.h"
+
+void zebra_mlag_init(void);
+void zebra_mlag_terminate(void);
+
+enum mlag_role zebra_mlag_get_role(void);
+#endif
diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c
index 9b86657f1b..03987fcb5b 100644
--- a/zebra/zebra_ns.c
+++ b/zebra/zebra_ns.c
@@ -73,6 +73,7 @@ static int zebra_ns_new(struct ns *ns)
zns = zebra_ns_alloc();
ns->info = zns;
zns->ns = ns;
+ zns->ns_id = ns->ns_id;
/* Do any needed per-NS data structure allocation. */
zns->if_table = route_table_init();
diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c
index 2e1c69fb92..ae18a0d290 100644
--- a/zebra/zebra_router.c
+++ b/zebra/zebra_router.c
@@ -25,6 +25,7 @@
#include "zebra_memory.h"
#include "zebra_pbr.h"
#include "zebra_vxlan.h"
+#include "zebra_mlag.h"
struct zebra_router zrouter;
@@ -159,6 +160,8 @@ void zebra_router_terminate(void)
}
zebra_vxlan_disable();
+ zebra_mlag_terminate();
+
hash_clean(zrouter.rules_hash, zebra_pbr_rules_free);
hash_free(zrouter.rules_hash);
@@ -173,6 +176,8 @@ void zebra_router_terminate(void)
void zebra_router_init(void)
{
zebra_vxlan_init();
+ zebra_mlag_init();
+
zrouter.rules_hash = hash_create_size(8, zebra_pbr_rules_hash_key,
zebra_pbr_rules_hash_equal,
"Rules Hash");
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 20dc64b0bc..b55ca60c00 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -412,7 +412,7 @@ static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
* this MAC update.
*/
if (zvrf->dad_freeze)
- *is_dup_detect = false;
+ *is_dup_detect = true;
return;
}
@@ -464,11 +464,6 @@ static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
if (is_local)
mac->dad_count++;
- zlog_debug("%s: MAC DAD %s dad_count %u ",
- __PRETTY_FUNCTION__,
- prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
- mac->dad_count);
-
if (mac->dad_count >= zvrf->dad_max_moves) {
flog_warn(EC_ZEBRA_DUP_MAC_DETECTED,
"VNI %u: MAC %s detected as duplicate during %s VTEP %s",
@@ -521,11 +516,11 @@ static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
&mac->dad_mac_auto_recovery_timer);
}
- /* Do not inform to client (BGPd),
+ /* In case of local update, do not inform to client (BGPd),
* upd_neigh for neigh sequence change.
*/
if (zvrf->dad_freeze)
- *is_dup_detect = false;
+ *is_dup_detect = true;
}
}
@@ -5176,11 +5171,11 @@ static void process_remote_macip_add(vni_t vni,
do_dad, &is_dup_detect,
false);
- zvni_process_neigh_on_remote_mac_add(zvni, mac);
-
- /* Install the entry. */
- if (!is_dup_detect)
+ if (!is_dup_detect) {
+ zvni_process_neigh_on_remote_mac_add(zvni, mac);
+ /* Install the entry. */
zvni_mac_install(zvni, mac);
+ }
}
/* Update seq number. */
@@ -6386,7 +6381,8 @@ int zebra_vxlan_clear_dup_detect_vni_mac(struct vty *vty,
* to BGP. Similarly remote macip update, neigh needs to be
* installed locally.
*/
- if (nbr->dad_count) {
+ if (zvrf->dad_freeze &&
+ CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL))
ZEBRA_NEIGH_SET_INACTIVE(nbr);
else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE))
@@ -6406,6 +6402,10 @@ int zebra_vxlan_clear_dup_detect_vni_mac(struct vty *vty,
mac->dad_dup_detect_time = 0;
THREAD_OFF(mac->dad_mac_auto_recovery_timer);
+ /* warn-only action return */
+ if (!zvrf->dad_freeze)
+ return CMD_SUCCESS;
+
/* Local: Notify Peer VTEPs, Remote: Install the entry */
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
/* Inform to BGP */
@@ -7412,6 +7412,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
bool mac_sticky = false;
bool inform_client = false;
bool upd_neigh = false;
+ bool is_dup_detect = false;
struct in_addr vtep_ip = {.s_addr = 0};
/* We are interested in MACs only on ports or (port, VLAN) that
@@ -7559,8 +7560,12 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
zebra_vxlan_dup_addr_detect_for_mac(zvrf, mac, vtep_ip,
do_dad,
- &inform_client,
+ &is_dup_detect,
true);
+ if (is_dup_detect) {
+ inform_client = false;
+ upd_neigh = false;
+ }
}
}
@@ -8971,7 +8976,7 @@ static int zebra_vxlan_dad_mac_auto_recovery_exp(struct thread *t)
/* Remove all IPs as duplicate associcated with this MAC */
for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, nbr)) {
- if (nbr->dad_count) {
+ if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL))
ZEBRA_NEIGH_SET_INACTIVE(nbr);
else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE))