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