]> git.proxmox.com Git - mirror_frr.git/blobdiff - ripd/ripd.c
Merge pull request #13555 from LabNConsulting/aceelindem/ospf-p2mp-delayed-reflooding...
[mirror_frr.git] / ripd / ripd.c
index bde7e858f1255f9de42957959d56fbd08d7da62e..04a8cad560fe25ae06be0cde144b5dfd9e8e3017 100644 (file)
@@ -11,7 +11,7 @@
 #include "command.h"
 #include "prefix.h"
 #include "table.h"
-#include "thread.h"
+#include "frrevent.h"
 #include "memory.h"
 #include "log.h"
 #include "stream.h"
@@ -34,6 +34,7 @@
 
 #include "ripd/ripd.h"
 #include "ripd/rip_nb.h"
+#include "ripd/rip_bfd.h"
 #include "ripd/rip_debug.h"
 #include "ripd/rip_errors.h"
 #include "ripd/rip_interface.h"
@@ -50,7 +51,7 @@ DEFINE_MTYPE_STATIC(RIPD, RIP_DISTANCE, "RIP distance");
 /* Prototypes. */
 static void rip_output_process(struct connected *, struct sockaddr_in *, int,
                               uint8_t);
-static void rip_triggered_update(struct thread *);
+static void rip_triggered_update(struct event *);
 static int rip_update_jitter(unsigned long);
 static void rip_distance_table_node_cleanup(struct route_table *table,
                                            struct route_node *node);
@@ -121,15 +122,15 @@ struct rip *rip_info_get_instance(const struct rip_info *rinfo)
 }
 
 /* RIP route garbage collect timer. */
-static void rip_garbage_collect(struct thread *t)
+static void rip_garbage_collect(struct event *t)
 {
        struct rip_info *rinfo;
        struct route_node *rp;
 
-       rinfo = THREAD_ARG(t);
+       rinfo = EVENT_ARG(t);
 
        /* Off timeout timer. */
-       THREAD_OFF(rinfo->t_timeout);
+       EVENT_OFF(rinfo->t_timeout);
 
        /* Get route_node pointer. */
        rp = rinfo->rp;
@@ -155,7 +156,10 @@ struct rip_info *rip_ecmp_add(struct rip *rip, struct rip_info *rinfo_new)
 {
        struct route_node *rp = rinfo_new->rp;
        struct rip_info *rinfo = NULL;
+       struct rip_info *rinfo_exist = NULL;
        struct list *list = NULL;
+       struct listnode *node = NULL;
+       struct listnode *nnode = NULL;
 
        if (rp->info == NULL)
                rp->info = list_new();
@@ -166,6 +170,33 @@ struct rip_info *rip_ecmp_add(struct rip *rip, struct rip_info *rinfo_new)
        if (listcount(list) && !rip->ecmp)
                return NULL;
 
+       /* Add or replace an existing ECMP path with lower neighbor IP */
+       if (listcount(list) && listcount(list) >= rip->ecmp) {
+               struct rip_info *from_highest = NULL;
+
+               /* Find the rip_info struct that has the highest nexthop IP */
+               for (ALL_LIST_ELEMENTS(list, node, nnode, rinfo_exist))
+                       if (!from_highest ||
+                           (from_highest &&
+                            IPV4_ADDR_CMP(&rinfo_exist->from,
+                                          &from_highest->from) > 0)) {
+                               from_highest = rinfo_exist;
+                       }
+
+               /* If we have a route in ECMP group, delete the old
+                * one that has a higher next-hop address. Lower IP is
+                * preferred.
+                */
+               if (rip->ecmp > 1 && from_highest &&
+                   IPV4_ADDR_CMP(&from_highest->from, &rinfo_new->from) > 0) {
+                       rip_ecmp_delete(rip, from_highest);
+                       goto add_or_replace;
+               }
+
+               return NULL;
+       }
+
+add_or_replace:
        rinfo = rip_info_new();
        memcpy(rinfo, rinfo_new, sizeof(struct rip_info));
        listnode_add(list, rinfo);
@@ -211,14 +242,14 @@ struct rip_info *rip_ecmp_replace(struct rip *rip, struct rip_info *rinfo_new)
                if (tmp_rinfo == rinfo)
                        continue;
 
-               THREAD_OFF(tmp_rinfo->t_timeout);
-               THREAD_OFF(tmp_rinfo->t_garbage_collect);
+               EVENT_OFF(tmp_rinfo->t_timeout);
+               EVENT_OFF(tmp_rinfo->t_garbage_collect);
                list_delete_node(list, node);
                rip_info_free(tmp_rinfo);
        }
 
-       THREAD_OFF(rinfo->t_timeout);
-       THREAD_OFF(rinfo->t_garbage_collect);
+       EVENT_OFF(rinfo->t_timeout);
+       EVENT_OFF(rinfo->t_garbage_collect);
        memcpy(rinfo, rinfo_new, sizeof(struct rip_info));
 
        if (rip_route_rte(rinfo)) {
@@ -247,12 +278,12 @@ struct rip_info *rip_ecmp_delete(struct rip *rip, struct rip_info *rinfo)
        struct route_node *rp = rinfo->rp;
        struct list *list = (struct list *)rp->info;
 
-       THREAD_OFF(rinfo->t_timeout);
+       EVENT_OFF(rinfo->t_timeout);
 
        if (listcount(list) > 1) {
                /* Some other ECMP entries still exist. Just delete this entry.
                 */
-               THREAD_OFF(rinfo->t_garbage_collect);
+               EVENT_OFF(rinfo->t_garbage_collect);
                listnode_delete(list, rinfo);
                if (rip_route_rte(rinfo)
                    && CHECK_FLAG(rinfo->flags, RIP_RTF_FIB))
@@ -287,9 +318,9 @@ struct rip_info *rip_ecmp_delete(struct rip *rip, struct rip_info *rinfo)
 }
 
 /* Timeout RIP routes. */
-static void rip_timeout(struct thread *t)
+static void rip_timeout(struct event *t)
 {
-       struct rip_info *rinfo = THREAD_ARG(t);
+       struct rip_info *rinfo = EVENT_ARG(t);
        struct rip *rip = rip_info_get_instance(rinfo);
 
        rip_ecmp_delete(rip, rinfo);
@@ -298,9 +329,9 @@ static void rip_timeout(struct thread *t)
 static void rip_timeout_update(struct rip *rip, struct rip_info *rinfo)
 {
        if (rinfo->metric != RIP_METRIC_INFINITY) {
-               THREAD_OFF(rinfo->t_timeout);
-               thread_add_timer(master, rip_timeout, rinfo, rip->timeout_time,
-                                &rinfo->t_timeout);
+               EVENT_OFF(rinfo->t_timeout);
+               event_add_timer(master, rip_timeout, rinfo, rip->timeout_time,
+                               &rinfo->t_timeout);
        }
 }
 
@@ -644,8 +675,8 @@ static void rip_rte_process(struct rte *rte, struct sockaddr_in *from,
                                        assert(newinfo.metric
                                               != RIP_METRIC_INFINITY);
 
-                                       THREAD_OFF(rinfo->t_timeout);
-                                       THREAD_OFF(rinfo->t_garbage_collect);
+                                       EVENT_OFF(rinfo->t_timeout);
+                                       EVENT_OFF(rinfo->t_garbage_collect);
                                        memcpy(rinfo, &newinfo,
                                               sizeof(struct rip_info));
                                        rip_timeout_update(rip, rinfo);
@@ -1123,7 +1154,7 @@ static void rip_response_process(struct rip_packet *packet, int size,
        if (from->sin_port != htons(RIP_PORT_DEFAULT)) {
                zlog_info("response doesn't come from RIP port: %d",
                          from->sin_port);
-               rip_peer_bad_packet(rip, from);
+               rip_peer_bad_packet(rip, ri, from);
                return;
        }
 
@@ -1137,7 +1168,7 @@ static void rip_response_process(struct rip_packet *packet, int size,
                zlog_info(
                        "This datagram doesn't come from a valid neighbor: %pI4",
                        &from->sin_addr);
-               rip_peer_bad_packet(rip, from);
+               rip_peer_bad_packet(rip, ri, from);
                return;
        }
 
@@ -1147,7 +1178,7 @@ static void rip_response_process(struct rip_packet *packet, int size,
        ; /* Alredy done in rip_read () */
 
        /* Update RIP peer. */
-       rip_peer_update(rip, from, packet->version);
+       rip_peer_update(rip, ri, from, packet->version);
 
        /* Set RTE pointer. */
        rte = packet->rte;
@@ -1171,12 +1202,18 @@ static void rip_response_process(struct rip_packet *packet, int size,
                        continue;
                }
 
+               if (packet->version == RIPv1 && rte->tag != 0) {
+                       zlog_warn("RIPv1 reserved field is nonzero: %d",
+                                 ntohs(rte->tag));
+                       continue;
+               }
+
                /* - is the destination address valid (e.g., unicast; not net 0
                   or 127) */
                if (!rip_destination_check(rte->prefix)) {
                        zlog_info(
                                "Network is net 0 or net 127 or it is not unicast network");
-                       rip_peer_bad_route(rip, from);
+                       rip_peer_bad_route(rip, ri, from);
                        continue;
                }
 
@@ -1186,7 +1223,7 @@ static void rip_response_process(struct rip_packet *packet, int size,
                /* - is the metric valid (i.e., between 1 and 16, inclusive) */
                if (!(rte->metric >= 1 && rte->metric <= 16)) {
                        zlog_info("Route's metric is not in the 1-16 range.");
-                       rip_peer_bad_route(rip, from);
+                       rip_peer_bad_route(rip, ri, from);
                        continue;
                }
 
@@ -1195,7 +1232,7 @@ static void rip_response_process(struct rip_packet *packet, int size,
                    && rte->nexthop.s_addr != INADDR_ANY) {
                        zlog_info("RIPv1 packet with nexthop value %pI4",
                                  &rte->nexthop);
-                       rip_peer_bad_route(rip, from);
+                       rip_peer_bad_route(rip, ri, from);
                        continue;
                }
 
@@ -1326,7 +1363,7 @@ static void rip_response_process(struct rip_packet *packet, int size,
                        zlog_warn(
                                "RIPv2 address %pI4 is not mask /%d applied one",
                                &rte->prefix, ip_masklen(rte->mask));
-                       rip_peer_bad_route(rip, from);
+                       rip_peer_bad_route(rip, ri, from);
                        continue;
                }
 
@@ -1500,7 +1537,7 @@ static int rip_send_packet(uint8_t *buf, int size, struct sockaddr_in *to,
        ret = sendmsg(rip->sock, &msg, 0);
 
        if (IS_RIP_DEBUG_EVENT)
-               zlog_debug("SEND to  %pI4%d", &sin.sin_addr,
+               zlog_debug("SEND to %pI4 port %d", &sin.sin_addr,
                           ntohs(sin.sin_port));
 
        if (ret < 0)
@@ -1598,7 +1635,7 @@ void rip_redistribute_delete(struct rip *rip, int type, int sub_type,
                                RIP_TIMER_ON(rinfo->t_garbage_collect,
                                             rip_garbage_collect,
                                             rip->garbage_time);
-                               THREAD_OFF(rinfo->t_timeout);
+                               EVENT_OFF(rinfo->t_timeout);
                                rinfo->flags |= RIP_RTF_CHANGED;
 
                                if (IS_RIP_DEBUG_EVENT)
@@ -1643,7 +1680,7 @@ static void rip_request_process(struct rip_packet *packet, int size,
                return;
 
        /* RIP peer update. */
-       rip_peer_update(rip, from, packet->version);
+       rip_peer_update(rip, ri, from, packet->version);
 
        lim = ((caddr_t)packet) + size;
        rte = packet->rte;
@@ -1697,9 +1734,9 @@ static void rip_request_process(struct rip_packet *packet, int size,
 }
 
 /* First entry point of RIP packet. */
-static void rip_read(struct thread *t)
+static void rip_read(struct event *t)
 {
-       struct rip *rip = THREAD_ARG(t);
+       struct rip *rip = EVENT_ARG(t);
        int sock;
        int ret;
        int rtenum;
@@ -1711,11 +1748,11 @@ static void rip_read(struct thread *t)
        socklen_t fromlen;
        struct interface *ifp = NULL;
        struct connected *ifc;
-       struct rip_interface *ri;
+       struct rip_interface *ri = NULL;
        struct prefix p;
 
        /* Fetch socket then register myself. */
-       sock = THREAD_FD(t);
+       sock = EVENT_FD(t);
 
        /* Add myself to tne next event */
        rip_event(rip, RIP_READ, sock);
@@ -1743,8 +1780,10 @@ static void rip_read(struct thread *t)
        /* Which interface is this packet comes from. */
        ifc = if_lookup_address((void *)&from.sin_addr, AF_INET,
                                rip->vrf->vrf_id);
-       if (ifc)
+       if (ifc) {
                ifp = ifc->ifp;
+               ri = ifp->info;
+       }
 
        /* RIP packet received */
        if (IS_RIP_DEBUG_EVENT)
@@ -1753,7 +1792,7 @@ static void rip_read(struct thread *t)
                           ifp ? ifp->name : "unknown", rip->vrf_name);
 
        /* If this packet come from unknown interface, ignore it. */
-       if (ifp == NULL) {
+       if (ifp == NULL || ri == NULL) {
                zlog_info(
                        "%s: cannot find interface for packet from %pI4 port %d (VRF %s)",
                        __func__, &from.sin_addr, ntohs(from.sin_port),
@@ -1779,13 +1818,13 @@ static void rip_read(struct thread *t)
        if (len < RIP_PACKET_MINSIZ) {
                zlog_warn("packet size %d is smaller than minimum size %d", len,
                          RIP_PACKET_MINSIZ);
-               rip_peer_bad_packet(rip, &from);
+               rip_peer_bad_packet(rip, ri, &from);
                return;
        }
        if (len > RIP_PACKET_MAXSIZ) {
                zlog_warn("packet size %d is larger than max size %d", len,
                          RIP_PACKET_MAXSIZ);
-               rip_peer_bad_packet(rip, &from);
+               rip_peer_bad_packet(rip, ri, &from);
                return;
        }
 
@@ -1793,7 +1832,7 @@ static void rip_read(struct thread *t)
        if ((len - RIP_PACKET_MINSIZ) % 20) {
                zlog_warn("packet size %d is wrong for RIP packet alignment",
                          len);
-               rip_peer_bad_packet(rip, &from);
+               rip_peer_bad_packet(rip, ri, &from);
                return;
        }
 
@@ -1807,7 +1846,7 @@ static void rip_read(struct thread *t)
        if (packet->version == 0) {
                zlog_info("version 0 with command %d received.",
                          packet->command);
-               rip_peer_bad_packet(rip, &from);
+               rip_peer_bad_packet(rip, ri, &from);
                return;
        }
 
@@ -1823,12 +1862,11 @@ static void rip_read(struct thread *t)
                packet->version = RIPv2;
 
        /* Is RIP running or is this RIP neighbor ?*/
-       ri = ifp->info;
        if (!ri->running && !rip_neighbor_lookup(rip, &from)) {
                if (IS_RIP_DEBUG_EVENT)
                        zlog_debug("RIP is not enabled on interface %s.",
                                   ifp->name);
-               rip_peer_bad_packet(rip, &from);
+               rip_peer_bad_packet(rip, ri, &from);
                return;
        }
 
@@ -1842,7 +1880,7 @@ static void rip_read(struct thread *t)
                        zlog_debug(
                                "  packet's v%d doesn't fit to if version spec",
                                packet->version);
-               rip_peer_bad_packet(rip, &from);
+               rip_peer_bad_packet(rip, ri, &from);
                return;
        }
 
@@ -1857,7 +1895,7 @@ static void rip_read(struct thread *t)
                                "packet RIPv%d is dropped because authentication disabled",
                                packet->version);
                ripd_notif_send_auth_type_failure(ifp->name);
-               rip_peer_bad_packet(rip, &from);
+               rip_peer_bad_packet(rip, ri, &from);
                return;
        }
 
@@ -1893,7 +1931,7 @@ static void rip_read(struct thread *t)
                                zlog_debug(
                                        "RIPv1 dropped because authentication enabled");
                        ripd_notif_send_auth_type_failure(ifp->name);
-                       rip_peer_bad_packet(rip, &from);
+                       rip_peer_bad_packet(rip, ri, &from);
                        return;
                }
        } else if (ri->auth_type != RIP_NO_AUTH) {
@@ -1906,7 +1944,7 @@ static void rip_read(struct thread *t)
                                zlog_debug(
                                        "RIPv2 authentication failed: no auth RTE in packet");
                        ripd_notif_send_auth_type_failure(ifp->name);
-                       rip_peer_bad_packet(rip, &from);
+                       rip_peer_bad_packet(rip, ri, &from);
                        return;
                }
 
@@ -1916,7 +1954,7 @@ static void rip_read(struct thread *t)
                                zlog_debug(
                                        "RIPv2 dropped because authentication enabled");
                        ripd_notif_send_auth_type_failure(ifp->name);
-                       rip_peer_bad_packet(rip, &from);
+                       rip_peer_bad_packet(rip, ri, &from);
                        return;
                }
 
@@ -1952,7 +1990,7 @@ static void rip_read(struct thread *t)
                                zlog_debug("RIPv2 %s authentication failure",
                                           auth_desc);
                        ripd_notif_send_auth_failure(ifp->name);
-                       rip_peer_bad_packet(rip, &from);
+                       rip_peer_bad_packet(rip, ri, &from);
                        return;
                }
        }
@@ -1971,16 +2009,16 @@ static void rip_read(struct thread *t)
                zlog_info(
                        "Obsolete command %s received, please sent it to routed",
                        lookup_msg(rip_msg, packet->command, NULL));
-               rip_peer_bad_packet(rip, &from);
+               rip_peer_bad_packet(rip, ri, &from);
                break;
        case RIP_POLL_ENTRY:
                zlog_info("Obsolete command %s received",
                          lookup_msg(rip_msg, packet->command, NULL));
-               rip_peer_bad_packet(rip, &from);
+               rip_peer_bad_packet(rip, ri, &from);
                break;
        default:
                zlog_info("Unknown RIP command %d received", packet->command);
-               rip_peer_bad_packet(rip, &from);
+               rip_peer_bad_packet(rip, ri, &from);
                break;
        }
 }
@@ -2478,9 +2516,9 @@ static void rip_update_process(struct rip *rip, int route_type)
 }
 
 /* RIP's periodical timer. */
-static void rip_update(struct thread *t)
+static void rip_update(struct event *t)
 {
-       struct rip *rip = THREAD_ARG(t);
+       struct rip *rip = EVENT_ARG(t);
 
        if (IS_RIP_DEBUG_EVENT)
                zlog_debug("update timer fire!");
@@ -2490,7 +2528,7 @@ static void rip_update(struct thread *t)
 
        /* Triggered updates may be suppressed if a regular update is due by
           the time the triggered update would be sent. */
-       THREAD_OFF(rip->t_triggered_interval);
+       EVENT_OFF(rip->t_triggered_interval);
        rip->trigger = 0;
 
        /* Register myself. */
@@ -2520,9 +2558,9 @@ static void rip_clear_changed_flag(struct rip *rip)
 }
 
 /* Triggered update interval timer. */
-static void rip_triggered_interval(struct thread *t)
+static void rip_triggered_interval(struct event *t)
 {
-       struct rip *rip = THREAD_ARG(t);
+       struct rip *rip = EVENT_ARG(t);
 
        if (rip->trigger) {
                rip->trigger = 0;
@@ -2531,13 +2569,13 @@ static void rip_triggered_interval(struct thread *t)
 }
 
 /* Execute triggered update. */
-static void rip_triggered_update(struct thread *t)
+static void rip_triggered_update(struct event *t)
 {
-       struct rip *rip = THREAD_ARG(t);
+       struct rip *rip = EVENT_ARG(t);
        int interval;
 
        /* Cancel interval timer. */
-       THREAD_OFF(rip->t_triggered_interval);
+       EVENT_OFF(rip->t_triggered_interval);
        rip->trigger = 0;
 
        /* Logging triggered update. */
@@ -2558,8 +2596,8 @@ static void rip_triggered_update(struct thread *t)
         update is triggered when the timer expires. */
        interval = (frr_weak_random() % 5) + 1;
 
-       thread_add_timer(master, rip_triggered_interval, rip, interval,
-                        &rip->t_triggered_interval);
+       event_add_timer(master, rip_triggered_interval, rip, interval,
+                       &rip->t_triggered_interval);
 }
 
 /* Withdraw redistributed route. */
@@ -2587,7 +2625,7 @@ void rip_redistribute_withdraw(struct rip *rip, int type)
                rinfo->metric = RIP_METRIC_INFINITY;
                RIP_TIMER_ON(rinfo->t_garbage_collect, rip_garbage_collect,
                             rip->garbage_time);
-               THREAD_OFF(rinfo->t_timeout);
+               EVENT_OFF(rinfo->t_timeout);
                rinfo->flags |= RIP_RTF_CHANGED;
 
                if (IS_RIP_DEBUG_EVENT) {
@@ -2624,6 +2662,36 @@ struct rip *rip_lookup_by_vrf_name(const char *vrf_name)
        return RB_FIND(rip_instance_head, &rip_instances, &rip);
 }
 
+/* Update ECMP routes to zebra when `allow-ecmp` changed. */
+void rip_ecmp_change(struct rip *rip)
+{
+       struct route_node *rp;
+       struct rip_info *rinfo;
+       struct list *list;
+       struct listnode *node, *nextnode;
+
+       for (rp = route_top(rip->table); rp; rp = route_next(rp)) {
+               list = rp->info;
+               if (list && listcount(list) > 1) {
+                       while (listcount(list) > rip->ecmp) {
+                               struct rip_info *from_highest = NULL;
+
+                               for (ALL_LIST_ELEMENTS(list, node, nextnode,
+                                                      rinfo)) {
+                                       if (!from_highest ||
+                                           (from_highest &&
+                                            IPV4_ADDR_CMP(
+                                                    &rinfo->from,
+                                                    &from_highest->from) > 0))
+                                               from_highest = rinfo;
+                               }
+
+                               rip_ecmp_delete(rip, from_highest);
+                       }
+               }
+       }
+}
+
 /* Create new RIP instance and set it to global variable. */
 struct rip *rip_create(const char *vrf_name, struct vrf *vrf, int socket)
 {
@@ -2633,7 +2701,7 @@ struct rip *rip_create(const char *vrf_name, struct vrf *vrf, int socket)
        rip->vrf_name = XSTRDUP(MTYPE_RIP_VRF_NAME, vrf_name);
 
        /* Set initial value. */
-       rip->ecmp = yang_get_default_bool("%s/allow-ecmp", RIP_INSTANCE);
+       rip->ecmp = yang_get_default_uint8("%s/allow-ecmp", RIP_INSTANCE);
        rip->default_metric =
                yang_get_default_uint8("%s/default-metric", RIP_INSTANCE);
        rip->distance =
@@ -2766,21 +2834,21 @@ void rip_event(struct rip *rip, enum rip_event event, int sock)
 
        switch (event) {
        case RIP_READ:
-               thread_add_read(master, rip_read, rip, sock, &rip->t_read);
+               event_add_read(master, rip_read, rip, sock, &rip->t_read);
                break;
        case RIP_UPDATE_EVENT:
-               THREAD_OFF(rip->t_update);
+               EVENT_OFF(rip->t_update);
                jitter = rip_update_jitter(rip->update_time);
-               thread_add_timer(master, rip_update, rip,
-                                sock ? 2 : rip->update_time + jitter,
-                                &rip->t_update);
+               event_add_timer(master, rip_update, rip,
+                               sock ? 2 : rip->update_time + jitter,
+                               &rip->t_update);
                break;
        case RIP_TRIGGERED_UPDATE:
                if (rip->t_triggered_interval)
                        rip->trigger = 1;
                else
-                       thread_add_event(master, rip_triggered_update, rip, 0,
-                                        &rip->t_triggered_update);
+                       event_add_event(master, rip_triggered_update, rip, 0,
+                                       &rip->t_triggered_update);
                break;
        default:
                break;
@@ -2836,16 +2904,11 @@ uint8_t rip_distance_apply(struct rip *rip, struct rip_info *rinfo)
                        if (access_list_apply(alist, &rinfo->rp->p)
                            == FILTER_DENY)
                                return 0;
-
-                       return rdistance->distance;
-               } else
-                       return rdistance->distance;
+               }
+               return rdistance->distance;
        }
 
-       if (rip->distance)
-               return rip->distance;
-
-       return 0;
+       return rip->distance;
 }
 
 static void rip_distance_show(struct vty *vty, struct rip *rip)
@@ -2899,8 +2962,8 @@ void rip_ecmp_disable(struct rip *rip)
                        if (tmp_rinfo == rinfo)
                                continue;
 
-                       THREAD_OFF(tmp_rinfo->t_timeout);
-                       THREAD_OFF(tmp_rinfo->t_garbage_collect);
+                       EVENT_OFF(tmp_rinfo->t_timeout);
+                       EVENT_OFF(tmp_rinfo->t_garbage_collect);
                        list_delete_node(list, node);
                        rip_info_free(tmp_rinfo);
                }
@@ -2923,15 +2986,15 @@ static void rip_vty_out_uptime(struct vty *vty, struct rip_info *rinfo)
        struct tm tm;
 #define TIME_BUF 25
        char timebuf[TIME_BUF];
-       struct thread *thread;
+       struct event *thread;
 
        if ((thread = rinfo->t_timeout) != NULL) {
-               clock = thread_timer_remain_second(thread);
+               clock = event_timer_remain_second(thread);
                gmtime_r(&clock, &tm);
                strftime(timebuf, TIME_BUF, "%M:%S", &tm);
                vty_out(vty, "%5s", timebuf);
        } else if ((thread = rinfo->t_garbage_collect) != NULL) {
-               clock = thread_timer_remain_second(thread);
+               clock = event_timer_remain_second(thread);
                gmtime_r(&clock, &tm);
                strftime(timebuf, TIME_BUF, "%M:%S", &tm);
                vty_out(vty, "%5s", timebuf);
@@ -3106,7 +3169,7 @@ DEFUN (show_ip_rip_status,
        vty_out(vty, "  Sending updates every %u seconds with +/-50%%,",
                rip->update_time);
        vty_out(vty, " next due in %lu seconds\n",
-               thread_timer_remain_second(rip->t_update));
+               event_timer_remain_second(rip->t_update));
        vty_out(vty, "  Timeout after %u seconds,", rip->timeout_time);
        vty_out(vty, " garbage collect after %u seconds\n", rip->garbage_time);
 
@@ -3209,9 +3272,6 @@ static int config_write_rip(struct vty *vty)
                /* Distribute configuration. */
                config_write_distribute(vty, rip->distribute_ctx);
 
-               /* Interface routemap configuration */
-               config_write_if_rmap(vty, rip->if_rmap_ctx);
-
                vty_out(vty, "exit\n");
 
                write = 1;
@@ -3347,6 +3407,7 @@ void rip_clean(struct rip *rip)
        route_table_finish(rip->distance_table);
 
        RB_REMOVE(rip_instance_head, &rip_instances, rip);
+       XFREE(MTYPE_RIP_BFD_PROFILE, rip->default_bfd_profile);
        XFREE(MTYPE_RIP_VRF_NAME, rip->vrf_name);
        XFREE(MTYPE_RIP, rip);
 }
@@ -3492,8 +3553,8 @@ static void rip_instance_disable(struct rip *rip)
                        rip_zebra_ipv4_delete(rip, rp);
 
                for (ALL_LIST_ELEMENTS_RO(list, listnode, rinfo)) {
-                       THREAD_OFF(rinfo->t_timeout);
-                       THREAD_OFF(rinfo->t_garbage_collect);
+                       EVENT_OFF(rinfo->t_timeout);
+                       EVENT_OFF(rinfo->t_garbage_collect);
                        rip_info_free(rinfo);
                }
                list_delete(&list);
@@ -3505,12 +3566,12 @@ static void rip_instance_disable(struct rip *rip)
        rip_redistribute_disable(rip);
 
        /* Cancel RIP related timers. */
-       THREAD_OFF(rip->t_update);
-       THREAD_OFF(rip->t_triggered_update);
-       THREAD_OFF(rip->t_triggered_interval);
+       EVENT_OFF(rip->t_update);
+       EVENT_OFF(rip->t_triggered_update);
+       EVENT_OFF(rip->t_triggered_interval);
 
        /* Cancel read thread. */
-       THREAD_OFF(rip->t_read);
+       EVENT_OFF(rip->t_read);
 
        /* Close RIP socket. */
        close(rip->sock);