diff options
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)) |
