summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_attr.c10
-rw-r--r--bgpd/bgp_attr.h8
-rw-r--r--bgpd/bgp_flowspec_util.c25
-rw-r--r--bgpd/bgp_flowspec_util.h4
-rw-r--r--bgpd/bgp_keepalives.c6
-rw-r--r--bgpd/bgp_mac.c354
-rw-r--r--bgpd/bgp_mac.h41
-rw-r--r--bgpd/bgp_nht.c11
-rw-r--r--bgpd/bgp_packet.c10
-rw-r--r--bgpd/bgp_pbr.c2
-rw-r--r--bgpd/bgp_pbr.h3
-rw-r--r--bgpd/bgp_route.c14
-rw-r--r--bgpd/bgp_vty.c22
-rw-r--r--bgpd/bgp_zebra.c9
-rw-r--r--bgpd/bgpd.c3
-rw-r--r--bgpd/bgpd.h5
-rw-r--r--bgpd/subdir.am2
-rw-r--r--debianpkg/frr.postinst15
-rw-r--r--doc/user/installation.rst12
-rw-r--r--doc/user/sharp.rst10
-rw-r--r--isisd/isis_northbound.c5
-rw-r--r--lib/frr_pthread.c30
-rw-r--r--lib/frr_pthread.h9
-rw-r--r--lib/mlag.c41
-rw-r--r--lib/mlag.h32
-rw-r--r--lib/subdir.am2
-rw-r--r--lib/thread.c7
-rw-r--r--lib/zclient.c1
-rw-r--r--lib/zclient.h3
-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--sharpd/sharp_vty.c71
-rw-r--r--sharpd/sharp_zebra.c61
-rw-r--r--sharpd/sharp_zebra.h6
-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
-rw-r--r--zebra/kernel_socket.c35
-rw-r--r--zebra/main.c5
-rw-r--r--zebra/subdir.am7
-rw-r--r--zebra/zapi_msg.c2
-rw-r--r--zebra/zebra_dplane.c44
-rw-r--r--zebra/zebra_dplane.h50
-rw-r--r--zebra/zebra_mlag.c83
-rw-r--r--zebra/zebra_mlag.h31
-rw-r--r--zebra/zebra_netns_notify.c12
-rw-r--r--zebra/zebra_ns.c7
-rw-r--r--zebra/zebra_ns.h2
-rw-r--r--zebra/zebra_rib.c113
-rw-r--r--zebra/zebra_rnh.c16
-rw-r--r--zebra/zebra_rnh.h1
-rw-r--r--zebra/zebra_router.c5
-rw-r--r--zebra/zebra_vxlan.c35
78 files changed, 1288 insertions, 490 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 87ebb9c285..03f31eddfc 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"},
@@ -392,7 +392,7 @@ static bool overlay_index_same(const struct attr *a1, const struct attr *a2)
if (!a1 && !a2)
return true;
return !memcmp(&(a1->evpn_overlay), &(a2->evpn_overlay),
- sizeof(struct overlay_index));
+ sizeof(struct bgp_route_evpn));
}
/* Unknown transit attribute. */
@@ -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_attr.h b/bgpd/bgp_attr.h
index 47a4182fee..6d5c647b21 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -92,12 +92,6 @@ struct bgp_tea_options {
#endif
-/* Overlay Index Info */
-struct overlay_index {
- struct eth_segment_id eth_s_id;
- union gw_addr gw_ip;
-};
-
enum pta_type {
PMSI_TNLTYPE_NO_INFO = 0,
PMSI_TNLTYPE_RSVP_TE_P2MP,
@@ -204,7 +198,7 @@ struct attr {
struct bgp_attr_encap_subtlv *vnc_subtlvs; /* VNC-specific */
#endif
/* EVPN */
- struct overlay_index evpn_overlay;
+ struct bgp_route_evpn evpn_overlay;
/* EVPN MAC Mobility sequence number, if any. */
uint32_t mm_seqnum;
diff --git a/bgpd/bgp_flowspec_util.c b/bgpd/bgp_flowspec_util.c
index c6386dcdb5..cd5bec6267 100644
--- a/bgpd/bgp_flowspec_util.c
+++ b/bgpd/bgp_flowspec_util.c
@@ -23,6 +23,7 @@
#include "prefix.h"
#include "lib_errors.h"
+#include "bgp_route.h"
#include "bgp_table.h"
#include "bgp_flowspec_util.h"
#include "bgp_flowspec_private.h"
@@ -581,3 +582,27 @@ int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
}
return error;
}
+
+/* return 1 if FS entry invalid or no NH IP */
+int bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi,
+ struct prefix *p)
+{
+ struct bgp_pbr_entry_main api;
+ int i;
+ struct bgp_node *rn = pi->net;
+ struct bgp_pbr_entry_action *api_action;
+
+ memset(&api, 0, sizeof(struct bgp_pbr_entry_main));
+ if (bgp_pbr_build_and_validate_entry(&rn->p, pi, &api) < 0)
+ return 1;
+ for (i = 0; i < api.action_num; i++) {
+ api_action = &api.actions[i];
+ if (api_action->action != ACTION_REDIRECT_IP)
+ continue;
+ p->family = AF_INET;
+ p->prefixlen = IPV4_MAX_BITLEN;
+ p->u.prefix4 = api_action->u.zr.redirect_ip_v4;
+ return 0;
+ }
+ return 1;
+}
diff --git a/bgpd/bgp_flowspec_util.h b/bgpd/bgp_flowspec_util.h
index 9bf05847d3..2ce911da4e 100644
--- a/bgpd/bgp_flowspec_util.h
+++ b/bgpd/bgp_flowspec_util.h
@@ -54,4 +54,8 @@ extern bool bgp_flowspec_contains_prefix(struct prefix *pfs,
struct prefix *input,
int prefix_check);
+extern int bgp_flowspec_get_first_nh(struct bgp *bgp,
+ struct bgp_path_info *pi,
+ struct prefix *nh);
+
#endif /* _FRR_BGP_FLOWSPEC_UTIL_H */
diff --git a/bgpd/bgp_keepalives.c b/bgpd/bgp_keepalives.c
index 50aad70ddc..87e3ff2495 100644
--- a/bgpd/bgp_keepalives.c
+++ b/bgpd/bgp_keepalives.c
@@ -181,7 +181,11 @@ void *bgp_keepalives_start(void *arg)
pthread_cond_init(peerhash_cond, &attrs);
pthread_condattr_destroy(&attrs);
- frr_pthread_set_name(fpt, NULL, "bgpd_ka");
+ /*
+ * We are not using normal FRR pthread mechanics and are
+ * not using fpt_run
+ */
+ frr_pthread_set_name(fpt);
/* initialize peer hashtable */
peerhash = hash_create_size(2048, peer_hash_key, peer_hash_cmp, NULL);
diff --git a/bgpd/bgp_mac.c b/bgpd/bgp_mac.c
new file mode 100644
index 0000000000..24f93e4373
--- /dev/null
+++ b/bgpd/bgp_mac.c
@@ -0,0 +1,354 @@
+/*
+ * BGPd - Mac hash code
+ * Copyright (C) 2018 Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <zebra.h>
+
+#include <jhash.h>
+#include <hash.h>
+#include <prefix.h>
+#include <memory.h>
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_mac.h"
+#include "bgpd/bgp_memory.h"
+#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_packet.h"
+#include "bgpd/bgp_debug.h"
+#include "bgpd/bgp_evpn_private.h"
+
+DEFINE_MTYPE_STATIC(BGPD, BSM, "Mac Hash Entry");
+DEFINE_MTYPE_STATIC(BGPD, BSM_STRING, "Mac Hash Entry Interface String");
+
+struct bgp_self_mac {
+ struct ethaddr macaddr;
+ struct list *ifp_list;
+};
+
+static unsigned int bgp_mac_hash_key_make(void *data)
+{
+ struct bgp_self_mac *bsm = data;
+
+ return jhash(&bsm->macaddr, ETH_ALEN, 0xa5a5dead);
+}
+
+static bool bgp_mac_hash_cmp(const void *d1, const void *d2)
+{
+ const struct bgp_self_mac *bsm1 = d1;
+ const struct bgp_self_mac *bsm2 = d2;
+
+ if (memcmp(&bsm1->macaddr, &bsm2->macaddr, ETH_ALEN) == 0)
+ return true;
+
+ return false;
+}
+
+void bgp_mac_init(void)
+{
+ bm->self_mac_hash = hash_create(bgp_mac_hash_key_make, bgp_mac_hash_cmp,
+ "BGP MAC Hash");
+}
+
+static void bgp_mac_hash_free(void *data)
+{
+ struct bgp_self_mac *bsm = data;
+
+ if (bsm->ifp_list)
+ list_delete(&bsm->ifp_list);
+
+ XFREE(MTYPE_BSM, bsm);
+}
+
+void bgp_mac_finish(void)
+{
+ hash_clean(bm->self_mac_hash, bgp_mac_hash_free);
+ hash_free(bm->self_mac_hash);
+}
+
+static void bgp_mac_hash_interface_string_del(void *val)
+{
+ char *data = val;
+
+ XFREE(MTYPE_BSM_STRING, data);
+}
+
+static void *bgp_mac_hash_alloc(void *p)
+{
+ const struct bgp_self_mac *orig = p;
+ struct bgp_self_mac *bsm;
+
+ bsm = XCALLOC(MTYPE_BSM, sizeof(struct bgp_self_mac));
+ memcpy(&bsm->macaddr, &orig->macaddr, ETH_ALEN);
+
+ bsm->ifp_list = list_new();
+ bsm->ifp_list->del = bgp_mac_hash_interface_string_del;
+
+ return bsm;
+}
+
+struct bgp_mac_find_internal {
+ struct bgp_self_mac *bsm;
+ const char *ifname;
+};
+
+static void bgp_mac_find_ifp_internal(struct hash_backet *backet, void *arg)
+{
+ struct bgp_mac_find_internal *bmfi = arg;
+ struct bgp_self_mac *bsm = backet->data;
+ struct listnode *node;
+ char *name;
+
+ for (ALL_LIST_ELEMENTS_RO(bsm->ifp_list, node, name)) {
+ if (strcmp(name, bmfi->ifname) == 0) {
+ bmfi->bsm = bsm;
+ return;
+ }
+ }
+}
+
+static struct bgp_self_mac *bgp_mac_find_interface_name(const char *ifname)
+{
+ struct bgp_mac_find_internal bmfi;
+
+ bmfi.bsm = NULL;
+ bmfi.ifname = ifname;
+ hash_iterate(bm->self_mac_hash, bgp_mac_find_ifp_internal, &bmfi);
+
+ return bmfi.bsm;
+}
+
+static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
+ struct bgp_table *table)
+{
+ struct bgp_node *prn, *rn;
+ struct bgp_path_info *pi;
+ uint32_t count = 0;
+
+ for (prn = bgp_table_top(table); prn; prn = bgp_route_next(prn)) {
+ struct bgp_table *sub = prn->info;
+
+ if (!sub)
+ continue;
+
+ for (rn = bgp_table_top(sub); rn; rn = bgp_route_next(rn)) {
+ struct prefix_rd prd;
+ uint32_t num_labels = 0;
+ mpls_label_t *label_pnt = NULL;
+ struct bgp_route_evpn evpn;
+
+ count++;
+ for (pi = rn->info; pi; pi = pi->next) {
+ if (pi->peer == peer)
+ break;
+ }
+
+ if (!pi)
+ continue;
+
+ if (pi->extra)
+ num_labels = pi->extra->num_labels;
+ if (num_labels)
+ label_pnt = &pi->extra->label[0];
+
+ prd.family = AF_UNSPEC;
+ prd.prefixlen = 64;
+ memcpy(&prd.val, &prn->p.u.val, 8);
+
+ memcpy(&evpn, &pi->attr->evpn_overlay, sizeof(evpn));
+ int32_t ret = bgp_update(peer, &rn->p,
+ pi->addpath_rx_id,
+ pi->attr, AFI_L2VPN, SAFI_EVPN,
+ ZEBRA_ROUTE_BGP,
+ BGP_ROUTE_NORMAL, &prd,
+ label_pnt, num_labels,
+ 1, &evpn);
+
+ if (ret < 0)
+ bgp_unlock_node(rn);
+ }
+ }
+}
+
+static void bgp_mac_rescan_evpn_table(struct bgp *bgp)
+{
+ struct listnode *node;
+ struct peer *peer;
+ safi_t safi;
+ afi_t afi;
+
+ afi = AFI_L2VPN;
+ safi = SAFI_EVPN;
+ for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
+
+ if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
+ continue;
+
+ if (peer->status != Established)
+ continue;
+
+ if (CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_SOFT_RECONFIG)) {
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("Processing EVPN MAC interface change on peer %s (inbound, soft-reconfig)",
+ peer->host);
+
+ bgp_soft_reconfig_in(peer, afi, safi);
+ } else {
+ struct bgp_table *table = bgp->rib[afi][safi];
+
+ if (bgp_debug_update(peer, NULL, NULL, 1))
+ zlog_debug("Processing EVPN MAC interface change on peer %s",
+ peer->host);
+ bgp_process_mac_rescan_table(bgp, peer, table);
+ }
+ }
+}
+
+static void bgp_mac_rescan_all_evpn_tables(void)
+{
+ struct listnode *node;
+ struct bgp *bgp;
+
+ for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
+ struct bgp_table *table = bgp->rib[AFI_L2VPN][SAFI_EVPN];
+
+ if (table)
+ bgp_mac_rescan_evpn_table(bgp);
+ }
+}
+
+static void bgp_mac_remove_ifp_internal(struct bgp_self_mac *bsm, char *ifname)
+{
+ struct listnode *node = NULL;
+ char *name;
+
+ for (ALL_LIST_ELEMENTS_RO(bsm->ifp_list, node, name)) {
+ if (strcmp(name, ifname) == 0)
+ break;
+ }
+
+ if (node) {
+ list_delete_node(bsm->ifp_list, node);
+ XFREE(MTYPE_BSM_STRING, name);
+ }
+
+ if (bsm->ifp_list->count == 0) {
+ hash_release(bm->self_mac_hash, bsm);
+ list_delete(&bsm->ifp_list);
+ XFREE(MTYPE_BSM, bsm);
+
+ bgp_mac_rescan_all_evpn_tables();
+ }
+}
+
+void bgp_mac_add_mac_entry(struct interface *ifp)
+{
+ struct bgp_self_mac lookup;
+ struct bgp_self_mac *bsm;
+ struct bgp_self_mac *old_bsm;
+ char *ifname;
+
+ memcpy(&lookup.macaddr, &ifp->hw_addr, ETH_ALEN);
+ bsm = hash_get(bm->self_mac_hash, &lookup, bgp_mac_hash_alloc);
+
+ /*
+ * Does this happen to be a move
+ */
+ old_bsm = bgp_mac_find_interface_name(ifp->name);
+ ifname = XSTRDUP(MTYPE_BSM_STRING, ifp->name);
+
+ if (bsm->ifp_list->count == 0) {
+
+ listnode_add(bsm->ifp_list, ifname);
+ if (old_bsm)
+ bgp_mac_remove_ifp_internal(old_bsm, ifname);
+ } else {
+ /*
+ * If old mac address is the same as the new,
+ * then there is nothing to do here
+ */
+ if (old_bsm == bsm)
+ return;
+
+ if (old_bsm)
+ bgp_mac_remove_ifp_internal(old_bsm, ifp->name);
+
+ listnode_add(bsm->ifp_list, ifname);
+ }
+
+ bgp_mac_rescan_all_evpn_tables();
+}
+
+void bgp_mac_del_mac_entry(struct interface *ifp)
+{
+ struct bgp_self_mac lookup;
+ struct bgp_self_mac *bsm;
+
+ memcpy(&lookup.macaddr, &ifp->hw_addr, ETH_ALEN);
+ bsm = hash_lookup(bm->self_mac_hash, &lookup);
+ if (!bsm)
+ return;
+
+ /*
+ * Write code to allow old mac address to no-longer
+ * win if we happen to have received it from a peer.
+ */
+ bgp_mac_remove_ifp_internal(bsm, ifp->name);
+}
+
+bool bgp_mac_entry_exists(struct prefix *p)
+{
+ struct prefix_evpn *pevpn = (struct prefix_evpn *)p;
+ struct bgp_self_mac lookup;
+ struct bgp_self_mac *bsm;
+
+ if (pevpn->family != AF_EVPN)
+ return false;
+
+ if (pevpn->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
+ return false;
+
+ memcpy(&lookup.macaddr, &p->u.prefix_evpn.macip_addr.mac, ETH_ALEN);
+ bsm = hash_lookup(bm->self_mac_hash, &lookup);
+ if (!bsm)
+ return false;
+
+ return true;
+}
+
+static void bgp_mac_show_mac_entry(struct hash_backet *backet, void *arg)
+{
+ struct vty *vty = arg;
+ struct bgp_self_mac *bsm = backet->data;
+ struct listnode *node;
+ char *name;
+ char buf_mac[ETHER_ADDR_STRLEN];
+
+ vty_out(vty, "Mac Address: %s ",
+ prefix_mac2str(&bsm->macaddr, buf_mac, sizeof(buf_mac)));
+
+ for (ALL_LIST_ELEMENTS_RO(bsm->ifp_list, node, name))
+ vty_out(vty, "%s ", name);
+
+ vty_out(vty, "\n");
+}
+
+void bgp_mac_dump_table(struct vty *vty)
+{
+ hash_iterate(bm->self_mac_hash, bgp_mac_show_mac_entry, vty);
+}
diff --git a/bgpd/bgp_mac.h b/bgpd/bgp_mac.h
new file mode 100644
index 0000000000..1dd987ef12
--- /dev/null
+++ b/bgpd/bgp_mac.h
@@ -0,0 +1,41 @@
+/*
+ * BGPd - Mac hash header
+ * Copyright (C) 2018 Cumulus Networks, Inc.
+ * Donald Sharp
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef __BGP_MAC_H__
+#define __BGP_MAC_H__
+
+void bgp_mac_init(void);
+void bgp_mac_finish(void);
+
+/*
+ * Functions to add/delete the mac entry from the appropriate
+ * bgp hash's. Additionally to do some additional processing
+ * to allow the win/loss to be processed.
+ */
+void bgp_mac_add_mac_entry(struct interface *ifp);
+void bgp_mac_del_mac_entry(struct interface *ifp);
+
+void bgp_mac_dump_table(struct vty *vty);
+
+/*
+ * Function to lookup the prefix and see if we have a matching mac
+ */
+bool bgp_mac_entry_exists(struct prefix *p);
+
+#endif
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index b6ef5a55c5..2b4ad22b93 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -42,6 +42,7 @@
#include "bgpd/bgp_nht.h"
#include "bgpd/bgp_fsm.h"
#include "bgpd/bgp_zebra.h"
+#include "bgpd/bgp_flowspec_util.h"
extern struct zclient *zclient;
@@ -533,7 +534,15 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
&& (pi->sub_type == BGP_ROUTE_STATIC))
? 1
: 0;
-
+ struct bgp_node *net = pi->net;
+ struct prefix *p_orig = &net->p;
+
+ if (p_orig->family == AF_FLOWSPEC) {
+ if (!pi->peer)
+ return -1;
+ return bgp_flowspec_get_first_nh(pi->peer->bgp,
+ pi, p);
+ }
memset(p, 0, sizeof(struct prefix));
switch (afi) {
case AFI_IP:
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_pbr.c b/bgpd/bgp_pbr.c
index f0a0e615e6..f002154701 100644
--- a/bgpd/bgp_pbr.c
+++ b/bgpd/bgp_pbr.c
@@ -626,7 +626,7 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api)
}
/* return -1 if build or validation failed */
-static int bgp_pbr_build_and_validate_entry(struct prefix *p,
+int bgp_pbr_build_and_validate_entry(struct prefix *p,
struct bgp_path_info *path,
struct bgp_pbr_entry_main *api)
{
diff --git a/bgpd/bgp_pbr.h b/bgpd/bgp_pbr.h
index 84095f9ab9..45c3c9ea13 100644
--- a/bgpd/bgp_pbr.h
+++ b/bgpd/bgp_pbr.h
@@ -290,4 +290,7 @@ extern void bgp_pbr_reset(struct bgp *bgp, afi_t afi);
extern struct bgp_pbr_interface *bgp_pbr_interface_lookup(const char *name,
struct bgp_pbr_interface_head *head);
+extern int bgp_pbr_build_and_validate_entry(struct prefix *p,
+ struct bgp_path_info *path,
+ struct bgp_pbr_entry_main *api);
#endif /* __BGP_PBR_H__ */
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 31cd3d1f05..3561674700 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -66,6 +66,7 @@
#include "bgpd/bgp_updgrp.h"
#include "bgpd/bgp_label.h"
#include "bgpd/bgp_addpath.h"
+#include "bgpd/bgp_mac.h"
#if ENABLE_BGP_VNC
#include "bgpd/rfapi/rfapi_backend.h"
@@ -3057,6 +3058,11 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id,
goto filtered;
}
+ if (bgp_mac_entry_exists(p)) {
+ reason = "self mac;";
+ goto filtered;
+ }
+
attr_new = bgp_attr_intern(&new_attr);
/* If the update is implicit withdraw. */
@@ -3778,16 +3784,22 @@ static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi,
bgp_node_get_bgp_path_info(rn);
uint32_t num_labels = 0;
mpls_label_t *label_pnt = NULL;
+ struct bgp_route_evpn evpn;
if (pi && pi->extra)
num_labels = pi->extra->num_labels;
if (num_labels)
label_pnt = &pi->extra->label[0];
+ if (pi)
+ memcpy(&evpn, &pi->attr->evpn_overlay,
+ sizeof(evpn));
+ else
+ memset(&evpn, 0, sizeof(evpn));
ret = bgp_update(peer, &rn->p, ain->addpath_rx_id,
ain->attr, afi, safi, ZEBRA_ROUTE_BGP,
BGP_ROUTE_NORMAL, prd, label_pnt,
- num_labels, 1, NULL);
+ num_labels, 1, &evpn);
if (ret < 0) {
bgp_unlock_node(rn);
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 2a4421aa54..cf1421f5a6 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -37,6 +37,7 @@
#include "frrstr.h"
#include "bgpd/bgpd.h"
+#include "bgpd/bgp_attr_evpn.h"
#include "bgpd/bgp_advertise.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_aspath.h"
@@ -62,6 +63,7 @@
#include "bgpd/bgp_io.h"
#include "bgpd/bgp_evpn.h"
#include "bgpd/bgp_addpath.h"
+#include "bgpd/bgp_mac.h"
static struct peer_group *listen_range_exists(struct bgp *bgp,
struct prefix *range, int exact);
@@ -7244,13 +7246,15 @@ static int bgp_clear_prefix(struct vty *vty, const char *view_name,
/* one clear bgp command to rule them all */
DEFUN (clear_ip_bgp_all,
clear_ip_bgp_all_cmd,
- "clear [ip] bgp [<view|vrf> VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]] <*|A.B.C.D|X:X::X:X|WORD|(1-4294967295)|external|peer-group WORD> [<soft [<in|out>]|in [prefix-filter]|out>]",
+ "clear [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6|l2vpn> [<unicast|multicast|vpn|labeled-unicast|flowspec|evpn>]] <*|A.B.C.D|X:X::X:X|WORD|(1-4294967295)|external|peer-group WORD> [<soft [<in|out>]|in [prefix-filter]|out>]",
CLEAR_STR
IP_STR
BGP_STR
BGP_INSTANCE_HELP_STR
BGP_AFI_HELP_STR
+ "Address Family\n"
BGP_SAFI_WITH_LABEL_HELP_STR
+ "Address Family modifier\n"
"Clear all peers\n"
"BGP neighbor address to clear\n"
"BGP IPv6 neighbor to clear\n"
@@ -7574,6 +7578,18 @@ DEFUN (show_bgp_vrfs,
return CMD_SUCCESS;
}
+DEFUN (show_bgp_mac_hash,
+ show_bgp_mac_hash_cmd,
+ "show bgp mac hash",
+ SHOW_STR
+ BGP_STR
+ "Mac Address\n"
+ "Mac Address database\n")
+{
+ bgp_mac_dump_table(vty);
+
+ return CMD_SUCCESS;
+}
static void show_tip_entry(struct hash_backet *backet, void *args)
{
@@ -12999,6 +13015,8 @@ void bgp_vty_init(void)
&neighbor_soft_reconfiguration_cmd);
install_element(BGP_FLOWSPECV6_NODE,
&no_neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_soft_reconfiguration_cmd);
+ install_element(BGP_EVPN_NODE, &no_neighbor_soft_reconfiguration_cmd);
/* "neighbor attribute-unchanged" commands. */
install_element(BGP_NODE, &neighbor_attr_unchanged_hidden_cmd);
@@ -13832,6 +13850,8 @@ void bgp_vty_init(void)
/* "show bgp martian next-hop" */
install_element(VIEW_NODE, &show_bgp_martian_nexthop_db_cmd);
+ install_element(VIEW_NODE, &show_bgp_mac_hash_cmd);
+
/* "show [ip] bgp views" commands. */
install_element(VIEW_NODE, &show_bgp_views_cmd);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 66d3333739..3c4b219466 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -59,6 +59,7 @@
#include "bgpd/bgp_labelpool.h"
#include "bgpd/bgp_pbr.h"
#include "bgpd/bgp_evpn_private.h"
+#include "bgpd/bgp_mac.h"
/* All information about zebra. */
struct zclient *zclient = NULL;
@@ -221,6 +222,8 @@ static int bgp_interface_add(int command, struct zclient *zclient,
if (!bgp)
return 0;
+ bgp_mac_add_mac_entry(ifp);
+
bgp_update_interface_nbrs(bgp, ifp, ifp);
return 0;
}
@@ -245,6 +248,8 @@ static int bgp_interface_delete(int command, struct zclient *zclient,
if (bgp)
bgp_update_interface_nbrs(bgp, ifp, NULL);
+ bgp_mac_del_mac_entry(ifp);
+
if_set_index(ifp, IFINDEX_INTERNAL);
return 0;
}
@@ -267,6 +272,8 @@ static int bgp_interface_up(int command, struct zclient *zclient,
if (!ifp)
return 0;
+ bgp_mac_add_mac_entry(ifp);
+
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("Rx Intf up VRF %u IF %s", vrf_id, ifp->name);
@@ -300,6 +307,8 @@ static int bgp_interface_down(int command, struct zclient *zclient,
if (!ifp)
return 0;
+ bgp_mac_del_mac_entry(ifp);
+
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("Rx Intf down VRF %u IF %s", vrf_id, ifp->name);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 7a3afbd18d..5b8ceb0541 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -87,6 +87,7 @@
#include "bgpd/bgp_pbr.h"
#include "bgpd/bgp_addpath.h"
#include "bgpd/bgp_evpn_private.h"
+#include "bgpd/bgp_mac.h"
DEFINE_MTYPE_STATIC(BGPD, PEER_TX_SHUTDOWN_MSG, "Peer shutdown message (TX)");
DEFINE_MTYPE_STATIC(BGPD, BGP_EVPN_INFO, "BGP EVPN instance information");
@@ -7775,6 +7776,7 @@ void bgp_master_init(struct thread_master *master)
bgp_process_queue_init();
+ bgp_mac_init();
/* init the rd id space.
assign 0th index in the bitfield,
so that we start with id 1
@@ -7964,4 +7966,5 @@ void bgp_terminate(void)
if (bm->t_rmap_update)
BGP_TIMER_OFF(bm->t_rmap_update);
+ bgp_mac_finish();
}
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 62096d651a..484fc105e8 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -122,6 +122,9 @@ struct bgp_master {
/* Listener address */
char *address;
+ /* The Mac table */
+ struct hash *self_mac_hash;
+
/* BGP start time. */
time_t start_time;
@@ -1280,7 +1283,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/bgpd/subdir.am b/bgpd/subdir.am
index 7d7d3ca189..7dd1d73f69 100644
--- a/bgpd/subdir.am
+++ b/bgpd/subdir.am
@@ -72,6 +72,7 @@ bgpd_libbgp_a_SOURCES = \
bgpd/bgp_label.c \
bgpd/bgp_labelpool.c \
bgpd/bgp_lcommunity.c \
+ bgpd/bgp_mac.c \
bgpd/bgp_memory.c \
bgpd/bgp_mpath.c \
bgpd/bgp_mplsvpn.c \
@@ -145,6 +146,7 @@ noinst_HEADERS += \
bgpd/bgp_label.h \
bgpd/bgp_labelpool.h \
bgpd/bgp_lcommunity.h \
+ bgpd/bgp_mac.h \
bgpd/bgp_memory.h \
bgpd/bgp_mpath.h \
bgpd/bgp_mplsvpn.h \
diff --git a/debianpkg/frr.postinst b/debianpkg/frr.postinst
index 32af741c98..a8d6ab2805 100644
--- a/debianpkg/frr.postinst
+++ b/debianpkg/frr.postinst
@@ -1,16 +1,13 @@
#!/bin/bash -e
######################
-PASSWDFILE=/etc/passwd
-GROUPFILE=/etc/group
+frruid=`getent passwd frr | awk -F ":" '{ print $3 }'`
+frrgid=`getent group frr | awk -F ":" '{ print $3 }'`
+frrvtygid=`getent group frrvty | awk -F ":" '{ print $3 }'`
-frruid=`egrep "^frr:" $PASSWDFILE | awk -F ":" '{ print $3 }'`
-frrgid=`egrep "^frr:" $GROUPFILE | awk -F ":" '{ print $3 }'`
-frrvtygid=`egrep "^frrvty:" $GROUPFILE | awk -F ":" '{ print $3 }'`
-
-[ -n ${frruid} ] || (echo "No uid for frr in ${PASSWDFILE}" && /bin/false)
-[ -n ${frrgid} ] || (echo "No gid for frr in ${GROUPFILE}" && /bin/false)
-[ -n ${frrVTYgid} ] || (echo "No gid for frrvty in ${GROUPFILE}" && /bin/false)
+[ -n ${frruid} ] || (echo "No uid for frr" && /bin/false)
+[ -n ${frrgid} ] || (echo "No gid for frr" && /bin/false)
+[ -n ${frrVTYgid} ] || (echo "No gid for frrvty" && /bin/false)
chown ${frruid}:${frrgid} /etc/frr
chown ${frruid}:${frrgid} /etc/frr/*
diff --git a/doc/user/installation.rst b/doc/user/installation.rst
index 9654cc2eb8..2decfcc4b2 100644
--- a/doc/user/installation.rst
+++ b/doc/user/installation.rst
@@ -324,7 +324,7 @@ GNU/Linux, make sure that the current kernel configuration is what you want.
FRR will run with any kernel configuration but some recommendations do exist.
:makevar:`CONFIG_NETLINK`
- Kernel/User Netlink socket. This is a enables an advanced interface between
+ Kernel/User Netlink socket. This enables an advanced interface between
the Linux kernel and *zebra* (:ref:`kernel-interface`).
:makevar:`CONFIG_RTNETLINK`
@@ -356,9 +356,9 @@ Additional kernel modules are also needed to support MPLS forwarding.
net.ipv6.conf.all.forwarding=1
:makevar:`MPLS forwarding`
- Basic MPLS kernel support was introduced 4.1, additional capability
- was introduced in 4.3 and 4.5. For some general information on Linux
- MPLS support see
+ Basic MPLS support was introduced in the kernel in version 4.1 and
+ additional capability was introduced in 4.3 and 4.5.
+ For some general information on Linux MPLS support, see
https://www.netdevconf.org/1.1/proceedings/slides/prabhu-mpls-tutorial.pdf.
The following modules should be loaded to support MPLS forwarding,
and are generally added to a configuration file such as
@@ -418,7 +418,7 @@ Additional kernel modules are also needed to support MPLS forwarding.
running these kernel versions, if unable to establish any VRF BGP
adjacencies, either downgrade to 4.13 or set
'net.ipv4.tcp_l3mdev_accept=1'. The fix for this issue is planned to be
- included in future kernel versions so upgrading your kernel may also
+ included in future kernel versions. So upgrading your kernel may also
address this issue.
@@ -440,7 +440,7 @@ the options you chose:
--enable-watchfrr \
...
-After configuring the software, you are ready to build and install it for your
+After configuring the software, you are ready to build and install it in your
system.
.. code-block:: shell
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/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/frr_pthread.c b/lib/frr_pthread.c
index a0223730b8..d5a2007c4d 100644
--- a/lib/frr_pthread.c
+++ b/lib/frr_pthread.c
@@ -84,6 +84,8 @@ struct frr_pthread *frr_pthread_new(struct frr_pthread_attr *attr,
fpt->name = XSTRDUP(MTYPE_FRR_PTHREAD, name);
if (os_name)
snprintf(fpt->os_name, OS_THREAD_NAMELEN, "%s", os_name);
+ else
+ snprintf(fpt->os_name, OS_THREAD_NAMELEN, "%s", name);
/* initialize startup synchronization primitives */
fpt->running_cond_mtx = XCALLOC(
MTYPE_PTHREAD_PRIM, sizeof(pthread_mutex_t));
@@ -115,36 +117,19 @@ void frr_pthread_destroy(struct frr_pthread *fpt)
XFREE(MTYPE_FRR_PTHREAD, fpt);
}
-int frr_pthread_set_name(struct frr_pthread *fpt, const char *name,
- const char *os_name)
+int frr_pthread_set_name(struct frr_pthread *fpt)
{
int ret = 0;
- if (name) {
- pthread_mutex_lock(&fpt->mtx);
- {
- if (fpt->name)
- XFREE(MTYPE_FRR_PTHREAD, fpt->name);
- fpt->name = XSTRDUP(MTYPE_FRR_PTHREAD, name);
- }
- pthread_mutex_unlock(&fpt->mtx);
- thread_master_set_name(fpt->master, name);
- }
-
- if (os_name) {
- pthread_mutex_lock(&fpt->mtx);
- snprintf(fpt->os_name, OS_THREAD_NAMELEN, "%s", os_name);
- pthread_mutex_unlock(&fpt->mtx);
#ifdef HAVE_PTHREAD_SETNAME_NP
# ifdef GNU_LINUX
- ret = pthread_setname_np(fpt->thread, fpt->os_name);
+ ret = pthread_setname_np(fpt->thread, fpt->os_name);
# else /* NetBSD */
- ret = pthread_setname_np(fpt->thread, fpt->os_name, NULL);
+ ret = pthread_setname_np(fpt->thread, fpt->os_name, NULL);
# endif
#elif defined(HAVE_PTHREAD_SET_NAME_NP)
- pthread_set_name_np(fpt->thread, fpt->os_name);
+ pthread_set_name_np(fpt->thread, fpt->os_name);
#endif
- }
return ret;
}
@@ -273,8 +258,7 @@ static void *fpt_run(void *arg)
fpt->master->handle_signals = false;
- if (fpt->os_name[0])
- frr_pthread_set_name(fpt, NULL, fpt->os_name);
+ frr_pthread_set_name(fpt);
frr_pthread_notify_running(fpt);
diff --git a/lib/frr_pthread.h b/lib/frr_pthread.h
index b9e60511d5..e6b3f031b3 100644
--- a/lib/frr_pthread.h
+++ b/lib/frr_pthread.h
@@ -133,16 +133,13 @@ struct frr_pthread *frr_pthread_new(struct frr_pthread_attr *attr,
const char *name, const char *os_name);
/*
- * Changes the name of the frr_pthread.
+ * Changes the name of the frr_pthread as reported by the operating
+ * system.
*
* @param fpt - the frr_pthread to operate on
- * @param name - Human-readable name
- * @param os_name - 16 characters thread name , including the null
- * terminator ('\0') to set in os.
* @return - on success returns 0 otherwise nonzero error number.
*/
-int frr_pthread_set_name(struct frr_pthread *fpt, const char *name,
- const char *os_name);
+int frr_pthread_set_name(struct frr_pthread *fpt);
/*
* Destroys an frr_pthread.
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/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/thread.c b/lib/thread.c
index 44c9e2b2f1..867ca2dc60 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -1572,8 +1572,13 @@ void thread_set_yield_time(struct thread *thread, unsigned long yield_time)
void thread_getrusage(RUSAGE_T *r)
{
+#if defined RUSAGE_THREAD
+#define FRR_RUSAGE RUSAGE_THREAD
+#else
+#define FRR_RUSAGE RUSAGE_SELF
+#endif
monotime(&r->real);
- getrusage(RUSAGE_SELF, &(r->cpu));
+ getrusage(FRR_RUSAGE, &(r->cpu));
}
/*
diff --git a/lib/zclient.c b/lib/zclient.c
index d2a6c75548..1c40750db0 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -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/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/sharpd/sharp_vty.c b/sharpd/sharp_vty.c
index 3aed8eb123..d0a34c0f93 100644
--- a/sharpd/sharp_vty.c
+++ b/sharpd/sharp_vty.c
@@ -40,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"
@@ -82,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>|nexthop-group NAME$nexthop_group> (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"
@@ -94,24 +102,27 @@ DEFPY (install_routes,
"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;
- struct nexthop_group nhg;
- uint32_t temp;
-
total_routes = routes;
installed_routes = 0;
- memset(&p, 0, sizeof(p));
+ if (rpt >= 2)
+ repeat = rpt * 2;
+ else
+ repeat = 0;
+
+ memset(&prefix, 0, sizeof(prefix));
+ memset(&orig_prefix, 0, sizeof(orig_prefix));
memset(&nhop, 0, sizeof(nhop));
- memset(&nhg, 0, sizeof(nhg));
+ memset(&nhop_group, 0, sizeof(nhop_group));
- p.family = AF_INET;
- p.prefixlen = 32;
- p.u.prefix4 = start;
+ 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);
@@ -122,7 +133,7 @@ DEFPY (install_routes,
return CMD_WARNING;
}
- nhg.nexthop = nhgc->nhg.nexthop;
+ nhop_group.nexthop = nhgc->nhg.nexthop;
} else {
if (nexthop4.s_addr != INADDR_ANY) {
nhop.gate.ipv4 = nexthop4;
@@ -132,15 +143,12 @@ DEFPY (install_routes,
nhop.type = NEXTHOP_TYPE_IPV6;
}
- nhg.nexthop = &nhop;
+ 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, &nhg);
- p.u.prefix4.s_addr = htonl(++temp);
- }
+ inst = instance;
+ rts = routes;
+ sharp_install_routes_helper(&prefix, inst, &nhop_group, rts);
return CMD_SUCCESS;
}
@@ -186,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;
-
- zlog_debug("Removing %ld routes", routes);
+ prefix.family = AF_INET;
+ prefix.prefixlen = 32;
+ prefix.u.prefix4 = start;
- 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 4a88b6c8ee..37591fa41f 100644
--- a/sharpd/sharp_zebra.c
+++ b/sharpd/sharp_zebra.c
@@ -132,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)
@@ -146,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");
@@ -157,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");
diff --git a/sharpd/sharp_zebra.h b/sharpd/sharp_zebra.h
index ffe21df9b8..7326056cae 100644
--- a/sharpd/sharp_zebra.h
+++ b/sharpd/sharp_zebra.h
@@ -29,4 +29,10 @@ 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/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/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/main.c b/zebra/main.c
index 90d3dbc180..b54c36c109 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -407,10 +407,7 @@ int main(int argc, char **argv)
/*
* Initialize NS( and implicitly the VRF module), and make kernel
* routing socket. */
- zebra_ns_init();
- if (vrf_default_name_configured)
- vrf_set_default_name(vrf_default_name_configured,
- true);
+ zebra_ns_init((const char *)vrf_default_name_configured);
zebra_vty_init();
access_list_init();
prefix_list_init();
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 32614f408e..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 -------------------------------------------------------- */
@@ -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_dplane.c b/zebra/zebra_dplane.c
index ba0f1b41aa..79e9e7edad 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -157,9 +157,9 @@ struct zebra_dplane_provider {
/* Flags */
int dp_flags;
- dplane_provider_process_fp dp_fp;
+ int (*dp_fp)(struct zebra_dplane_provider *prov);
- dplane_provider_fini_fp dp_fini;
+ int (*dp_fini)(struct zebra_dplane_provider *prov, bool early_p);
_Atomic uint32_t dp_in_counter;
_Atomic uint32_t dp_in_queued;
@@ -189,7 +189,7 @@ static struct zebra_dplane_globals {
pthread_mutex_t dg_mutex;
/* Results callback registered by zebra 'core' */
- dplane_results_fp dg_results_cb;
+ int (*dg_results_cb)(struct dplane_ctx_q *ctxlist);
/* Sentinel for beginning of shutdown */
volatile bool dg_is_shutdown;
@@ -988,8 +988,9 @@ int dplane_show_provs_helper(struct vty *vty, bool detailed)
int dplane_provider_register(const char *name,
enum dplane_provider_prio prio,
int flags,
- dplane_provider_process_fp fp,
- dplane_provider_fini_fp fini_fp,
+ int (*fp)(struct zebra_dplane_provider *),
+ int (*fini_fp)(struct zebra_dplane_provider *,
+ bool early),
void *data)
{
int ret = 0;
@@ -1210,15 +1211,6 @@ int dplane_provider_work_ready(void)
}
/*
- * Zebra registers a results callback with the dataplane system
- */
-int dplane_results_register(dplane_results_fp fp)
-{
- zdplane_info.dg_results_cb = fp;
- return AOK;
-}
-
-/*
* Kernel dataplane provider
*/
@@ -1677,27 +1669,20 @@ static int dplane_thread_loop(struct thread *event)
counter, error_counter);
/*
- * TODO -- I'd rather hand lists through the api to zebra main,
+ * Hand lists through the api to zebra main,
* to reduce the number of lock/unlock cycles
*/
- for (ctx = TAILQ_FIRST(&error_list); ctx; ) {
- TAILQ_REMOVE(&error_list, ctx, zd_q_entries);
- /* Call through to zebra main */
- (*zdplane_info.dg_results_cb)(ctx);
-
- ctx = TAILQ_FIRST(&error_list);
- }
+ /* Call through to zebra main */
+ (zdplane_info.dg_results_cb)(&error_list);
+ TAILQ_INIT(&error_list);
- for (ctx = TAILQ_FIRST(&work_list); ctx; ) {
- TAILQ_REMOVE(&work_list, ctx, zd_q_entries);
- /* Call through to zebra main */
- (*zdplane_info.dg_results_cb)(ctx);
+ /* Call through to zebra main */
+ (zdplane_info.dg_results_cb)(&work_list);
- ctx = TAILQ_FIRST(&work_list);
- }
+ TAILQ_INIT(&work_list);
done:
return 0;
@@ -1782,7 +1767,8 @@ void zebra_dplane_start(void)
/*
* Initialize the dataplane module at startup; called by zebra rib_init()
*/
-void zebra_dplane_init(void)
+void zebra_dplane_init(int (*results_fp)(struct dplane_ctx_q *))
{
zebra_dplane_init_internal(&zebrad);
+ zdplane_info.dg_results_cb = results_fp;
}
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index 1336850510..1d23ef0f82 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -250,21 +250,6 @@ enum dplane_provider_prio {
DPLANE_PRIO_LAST
};
-/* Provider's entry-point for incoming work, called in the context of the
- * dataplane pthread. The dataplane pthread enqueues any new work to the
- * provider's 'inbound' queue, then calls the callback. The dataplane
- * then checks the provider's outbound queue.
- */
-typedef int (*dplane_provider_process_fp)(struct zebra_dplane_provider *prov);
-
-/* Provider's entry-point for shutdown and cleanup. Called with 'early'
- * during shutdown, to indicate that the dataplane subsystem is allowing
- * work to move through the providers and finish. When called without 'early',
- * the provider should release all resources (if it has any allocated).
- */
-typedef int (*dplane_provider_fini_fp)(struct zebra_dplane_provider *prov,
- bool early);
-
/* Flags values used during provider registration. */
#define DPLANE_PROV_FLAGS_DEFAULT 0x0
@@ -275,11 +260,25 @@ typedef int (*dplane_provider_fini_fp)(struct zebra_dplane_provider *prov,
/* Provider registration: ordering or priority value, callbacks, and optional
* opaque data value.
*/
+
+/* Providers offer an entry-point for incoming work, called in the context of
+ * the dataplane pthread. The dataplane pthread enqueues any new work to the
+ * provider's 'inbound' queue, then calls the callback. The dataplane
+ * then checks the provider's outbound queue for completed work.
+ */
+
+/* Providers offer an entry-point for shutdown and cleanup. This is called
+ * with 'early' during shutdown, to indicate that the dataplane subsystem
+ * is allowing work to move through the providers and finish.
+ * When called without 'early', the provider should release
+ * all resources (if it has any allocated).
+ */
int dplane_provider_register(const char *name,
enum dplane_provider_prio prio,
int flags,
- dplane_provider_process_fp fp,
- dplane_provider_fini_fp fini_fp,
+ int (*fp)(struct zebra_dplane_provider *),
+ int (*fini_fp)(struct zebra_dplane_provider *,
+ bool early),
void *data);
/* Accessors for provider attributes */
@@ -318,20 +317,13 @@ void dplane_provider_enqueue_out_ctx(struct zebra_dplane_provider *prov,
struct zebra_dplane_ctx *ctx);
/*
- * Zebra registers a results callback with the dataplane. The callback is
- * called in the dataplane pthread context, so the expectation is that the
- * context is queued for the zebra main pthread or that processing
- * is very limited.
- */
-typedef int (*dplane_results_fp)(struct zebra_dplane_ctx *ctx);
-
-int dplane_results_register(dplane_results_fp fp);
-
-/*
* Initialize the dataplane modules at zebra startup. This is currently called
- * by the rib module.
+ * by the rib module. Zebra registers a results callback with the dataplane.
+ * The callback is called in the dataplane pthread context,
+ * so the expectation is that the contexts are queued for the zebra
+ * main pthread.
*/
-void zebra_dplane_init(void);
+void zebra_dplane_init(int (*) (struct dplane_ctx_q *));
/*
* Start the dataplane pthread. This step needs to be run later than the
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_netns_notify.c b/zebra/zebra_netns_notify.c
index ed9f3899d4..ef31fcf45d 100644
--- a/zebra/zebra_netns_notify.c
+++ b/zebra/zebra_netns_notify.c
@@ -215,6 +215,12 @@ static int zebra_ns_ready_read(struct thread *t)
if (err < 0)
return zebra_ns_continue_read(zns_info, stop_retry);
+ /* check default name is not already set */
+ if (strmatch(VRF_DEFAULT_NAME, basename(netnspath))) {
+ zlog_warn("NS notify : NS %s is already default VRF."
+ "Cancel VRF Creation", basename(netnspath));
+ return zebra_ns_continue_read(zns_info, 1);
+ }
if (zebra_ns_notify_is_default_netns(basename(netnspath))) {
zlog_warn(
"NS notify : NS %s is default VRF."
@@ -312,6 +318,12 @@ void zebra_ns_notify_parse(void)
dent->d_name);
continue;
}
+ /* check default name is not already set */
+ if (strmatch(VRF_DEFAULT_NAME, basename(dent->d_name))) {
+ zlog_warn("NS notify : NS %s is already default VRF."
+ "Cancel VRF Creation", dent->d_name);
+ continue;
+ }
if (zebra_ns_notify_is_default_netns(dent->d_name)) {
zlog_warn(
"NS notify : NS %s is default VRF."
diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c
index 9b86657f1b..0c743d8678 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();
@@ -182,7 +183,7 @@ int zebra_ns_final_shutdown(struct ns *ns)
return 0;
}
-int zebra_ns_init(void)
+int zebra_ns_init(const char *optional_default_name)
{
ns_id_t ns_id;
ns_id_t ns_id_external;
@@ -206,6 +207,10 @@ int zebra_ns_init(void)
/* Default NS is activated */
zebra_ns_enable(ns_id_external, (void **)&dzns);
+ if (optional_default_name)
+ vrf_set_default_name(optional_default_name,
+ true);
+
if (vrf_is_backend_netns()) {
ns_add_hook(NS_NEW_HOOK, zebra_ns_new);
ns_add_hook(NS_ENABLE_HOOK, zebra_ns_enabled);
diff --git a/zebra/zebra_ns.h b/zebra/zebra_ns.h
index d3592f8f30..01af64c17b 100644
--- a/zebra/zebra_ns.h
+++ b/zebra/zebra_ns.h
@@ -60,7 +60,7 @@ struct zebra_ns {
struct zebra_ns *zebra_ns_lookup(ns_id_t ns_id);
-int zebra_ns_init(void);
+int zebra_ns_init(const char *optional_default_name);
int zebra_ns_enable(ns_id_t ns_id, void **info);
int zebra_ns_disabled(struct ns *ns);
int zebra_ns_early_shutdown(struct ns *ns);
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 5d6eac7533..b4b19693e6 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -73,31 +73,32 @@ extern int allow_delete;
static const struct {
int key;
int distance;
+ uint8_t meta_q_map;
} route_info[ZEBRA_ROUTE_MAX] = {
- [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0},
- [ZEBRA_ROUTE_KERNEL] = {ZEBRA_ROUTE_KERNEL, 0},
- [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT, 0},
- [ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC, 1},
- [ZEBRA_ROUTE_RIP] = {ZEBRA_ROUTE_RIP, 120},
- [ZEBRA_ROUTE_RIPNG] = {ZEBRA_ROUTE_RIPNG, 120},
- [ZEBRA_ROUTE_OSPF] = {ZEBRA_ROUTE_OSPF, 110},
- [ZEBRA_ROUTE_OSPF6] = {ZEBRA_ROUTE_OSPF6, 110},
- [ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115},
- [ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */},
- [ZEBRA_ROUTE_PIM] = {ZEBRA_ROUTE_PIM, 255},
- [ZEBRA_ROUTE_EIGRP] = {ZEBRA_ROUTE_EIGRP, 90},
- [ZEBRA_ROUTE_NHRP] = {ZEBRA_ROUTE_NHRP, 10},
- [ZEBRA_ROUTE_HSLS] = {ZEBRA_ROUTE_HSLS, 255},
- [ZEBRA_ROUTE_OLSR] = {ZEBRA_ROUTE_OLSR, 255},
- [ZEBRA_ROUTE_TABLE] = {ZEBRA_ROUTE_TABLE, 150},
- [ZEBRA_ROUTE_LDP] = {ZEBRA_ROUTE_LDP, 150},
- [ZEBRA_ROUTE_VNC] = {ZEBRA_ROUTE_VNC, 20},
- [ZEBRA_ROUTE_VNC_DIRECT] = {ZEBRA_ROUTE_VNC_DIRECT, 20},
- [ZEBRA_ROUTE_VNC_DIRECT_RH] = {ZEBRA_ROUTE_VNC_DIRECT_RH, 20},
- [ZEBRA_ROUTE_BGP_DIRECT] = {ZEBRA_ROUTE_BGP_DIRECT, 20},
- [ZEBRA_ROUTE_BGP_DIRECT_EXT] = {ZEBRA_ROUTE_BGP_DIRECT_EXT, 20},
- [ZEBRA_ROUTE_BABEL] = {ZEBRA_ROUTE_BABEL, 100},
- [ZEBRA_ROUTE_SHARP] = {ZEBRA_ROUTE_SHARP, 150},
+ [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0, 4},
+ [ZEBRA_ROUTE_KERNEL] = {ZEBRA_ROUTE_KERNEL, 0, 0},
+ [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT, 0, 0},
+ [ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC, 1, 1},
+ [ZEBRA_ROUTE_RIP] = {ZEBRA_ROUTE_RIP, 120, 2},
+ [ZEBRA_ROUTE_RIPNG] = {ZEBRA_ROUTE_RIPNG, 120, 2},
+ [ZEBRA_ROUTE_OSPF] = {ZEBRA_ROUTE_OSPF, 110, 2},
+ [ZEBRA_ROUTE_OSPF6] = {ZEBRA_ROUTE_OSPF6, 110, 2},
+ [ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115, 2},
+ [ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */, 3},
+ [ZEBRA_ROUTE_PIM] = {ZEBRA_ROUTE_PIM, 255, 4},
+ [ZEBRA_ROUTE_EIGRP] = {ZEBRA_ROUTE_EIGRP, 90, 2},
+ [ZEBRA_ROUTE_NHRP] = {ZEBRA_ROUTE_NHRP, 10, 2},
+ [ZEBRA_ROUTE_HSLS] = {ZEBRA_ROUTE_HSLS, 255, 4},
+ [ZEBRA_ROUTE_OLSR] = {ZEBRA_ROUTE_OLSR, 255, 4},
+ [ZEBRA_ROUTE_TABLE] = {ZEBRA_ROUTE_TABLE, 150, 1},
+ [ZEBRA_ROUTE_LDP] = {ZEBRA_ROUTE_LDP, 150, 4},
+ [ZEBRA_ROUTE_VNC] = {ZEBRA_ROUTE_VNC, 20, 3},
+ [ZEBRA_ROUTE_VNC_DIRECT] = {ZEBRA_ROUTE_VNC_DIRECT, 20, 3},
+ [ZEBRA_ROUTE_VNC_DIRECT_RH] = {ZEBRA_ROUTE_VNC_DIRECT_RH, 20, 3},
+ [ZEBRA_ROUTE_BGP_DIRECT] = {ZEBRA_ROUTE_BGP_DIRECT, 20, 3},
+ [ZEBRA_ROUTE_BGP_DIRECT_EXT] = {ZEBRA_ROUTE_BGP_DIRECT_EXT, 20, 3},
+ [ZEBRA_ROUTE_BABEL] = {ZEBRA_ROUTE_BABEL, 100, 2},
+ [ZEBRA_ROUTE_SHARP] = {ZEBRA_ROUTE_SHARP, 150, 4},
/* no entry/default: 150 */
};
@@ -2143,36 +2144,6 @@ static wq_item_status meta_queue_process(struct work_queue *dummy, void *data)
return mq->size ? WQ_REQUEUE : WQ_SUCCESS;
}
-/*
- * Map from rib types to queue type (priority) in meta queue
- */
-static const uint8_t meta_queue_map[ZEBRA_ROUTE_MAX] = {
- [ZEBRA_ROUTE_SYSTEM] = 4,
- [ZEBRA_ROUTE_KERNEL] = 0,
- [ZEBRA_ROUTE_CONNECT] = 0,
- [ZEBRA_ROUTE_STATIC] = 1,
- [ZEBRA_ROUTE_RIP] = 2,
- [ZEBRA_ROUTE_RIPNG] = 2,
- [ZEBRA_ROUTE_OSPF] = 2,
- [ZEBRA_ROUTE_OSPF6] = 2,
- [ZEBRA_ROUTE_ISIS] = 2,
- [ZEBRA_ROUTE_BGP] = 3,
- [ZEBRA_ROUTE_PIM] = 4, // Shouldn't happen but for safety
- [ZEBRA_ROUTE_EIGRP] = 2,
- [ZEBRA_ROUTE_NHRP] = 2,
- [ZEBRA_ROUTE_HSLS] = 4,
- [ZEBRA_ROUTE_OLSR] = 4,
- [ZEBRA_ROUTE_TABLE] = 1,
- [ZEBRA_ROUTE_LDP] = 4,
- [ZEBRA_ROUTE_VNC] = 3,
- [ZEBRA_ROUTE_VNC_DIRECT] = 3,
- [ZEBRA_ROUTE_VNC_DIRECT_RH] = 3,
- [ZEBRA_ROUTE_BGP_DIRECT] = 3,
- [ZEBRA_ROUTE_BGP_DIRECT_EXT] = 3,
- [ZEBRA_ROUTE_BABEL] = 2,
- [ZEBRA_ROUTE_ALL] = 4, // Shouldn't happen but for safety
-};
-
/* Look into the RN and queue it into one or more priority queues,
* increasing the size for each data push done.
*/
@@ -2181,7 +2152,7 @@ static void rib_meta_queue_add(struct meta_queue *mq, struct route_node *rn)
struct route_entry *re;
RNODE_FOREACH_RE (rn, re) {
- uint8_t qindex = meta_queue_map[re->type];
+ uint8_t qindex = route_info[re->type].meta_q_map;
struct zebra_vrf *zvrf;
/* Invariant: at this point we always have rn->info set. */
@@ -3194,21 +3165,34 @@ void rib_close_table(struct route_table *table)
static int rib_process_dplane_results(struct thread *thread)
{
struct zebra_dplane_ctx *ctx;
+ struct dplane_ctx_q ctxlist;
+
+ /* Dequeue a list of completed updates with one lock/unlock cycle */
do {
+ TAILQ_INIT(&ctxlist);
+
/* Take lock controlling queue of results */
pthread_mutex_lock(&dplane_mutex);
{
/* Dequeue context block */
- ctx = dplane_ctx_dequeue(&rib_dplane_q);
+ dplane_ctx_list_append(&ctxlist, &rib_dplane_q);
}
pthread_mutex_unlock(&dplane_mutex);
- if (ctx)
- rib_process_after(ctx);
- else
+ /* Dequeue context block */
+ ctx = dplane_ctx_dequeue(&ctxlist);
+
+ /* If we've emptied the results queue, we're done */
+ if (ctx == NULL)
break;
+ while (ctx) {
+ rib_process_after(ctx);
+
+ ctx = dplane_ctx_dequeue(&ctxlist);
+ }
+
} while (1);
/* Check for nexthop tracking processing after finishing with results */
@@ -3222,17 +3206,17 @@ static int rib_process_dplane_results(struct thread *thread)
* the dataplane pthread. We enqueue the results here for processing by
* the main thread later.
*/
-static int rib_dplane_results(struct zebra_dplane_ctx *ctx)
+static int rib_dplane_results(struct dplane_ctx_q *ctxlist)
{
/* Take lock controlling queue of results */
pthread_mutex_lock(&dplane_mutex);
{
- /* Enqueue context block */
- dplane_ctx_enqueue_tail(&rib_dplane_q, ctx);
+ /* Enqueue context blocks */
+ dplane_ctx_list_append(&rib_dplane_q, ctxlist);
}
pthread_mutex_unlock(&dplane_mutex);
- /* Ensure event is signalled to zebra main thread */
+ /* Ensure event is signalled to zebra main pthread */
thread_add_event(zebrad.master, rib_process_dplane_results, NULL, 0,
&t_dplane);
@@ -3247,8 +3231,7 @@ void rib_init(void)
/* Init dataplane, and register for results */
pthread_mutex_init(&dplane_mutex, NULL);
TAILQ_INIT(&rib_dplane_q);
- zebra_dplane_init();
- dplane_results_register(rib_dplane_results);
+ zebra_dplane_init(rib_dplane_results);
}
/*
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index b1fbe8a653..c3781888b1 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -178,11 +178,15 @@ void zebra_free_rnh(struct rnh *rnh)
XFREE(MTYPE_RNH, rnh);
}
-void zebra_delete_rnh(struct rnh *rnh, rnh_type_t type)
+static void zebra_delete_rnh(struct rnh *rnh, rnh_type_t type)
{
struct route_node *rn;
- if (!rnh || (rnh->flags & ZEBRA_NHT_DELETED) || !(rn = rnh->node))
+ if (!list_isempty(rnh->client_list)
+ || !list_isempty(rnh->zebra_pseudowire_list))
+ return;
+
+ if ((rnh->flags & ZEBRA_NHT_DELETED) || !(rn = rnh->node))
return;
if (IS_ZEBRA_DEBUG_NHT) {
@@ -233,9 +237,7 @@ void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client,
rnh_str(rnh, buf, sizeof(buf)), type);
}
listnode_delete(rnh->client_list, client);
- if (list_isempty(rnh->client_list)
- && list_isempty(rnh->zebra_pseudowire_list))
- zebra_delete_rnh(rnh, type);
+ zebra_delete_rnh(rnh, type);
}
/* XXX move this utility function elsewhere? */
@@ -291,9 +293,7 @@ void zebra_deregister_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw)
listnode_delete(rnh->zebra_pseudowire_list, pw);
pw->rnh = NULL;
- if (list_isempty(rnh->client_list)
- && list_isempty(rnh->zebra_pseudowire_list))
- zebra_delete_rnh(rnh, RNH_NEXTHOP_TYPE);
+ zebra_delete_rnh(rnh, RNH_NEXTHOP_TYPE);
}
/* Apply the NHT route-map for a client to the route (and nexthops)
diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h
index 33302f0ee2..ed1fe9b756 100644
--- a/zebra/zebra_rnh.h
+++ b/zebra/zebra_rnh.h
@@ -72,7 +72,6 @@ extern struct rnh *zebra_add_rnh(struct prefix *p, vrf_id_t vrfid,
extern struct rnh *zebra_lookup_rnh(struct prefix *p, vrf_id_t vrfid,
rnh_type_t type);
extern void zebra_free_rnh(struct rnh *rnh);
-extern void zebra_delete_rnh(struct rnh *rnh, rnh_type_t type);
extern void zebra_add_rnh_client(struct rnh *rnh, struct zserv *client,
rnh_type_t type, vrf_id_t vrfid);
extern void zebra_register_rnh_pseudowire(vrf_id_t, struct zebra_pw *);
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))