]> git.proxmox.com Git - mirror_frr.git/blobdiff - ospfd/ospfd.c
Merge pull request #1428 from LabNConsulting/working/master/indent
[mirror_frr.git] / ospfd / ospfd.c
index 8ee32289c175dc20a3361f3452e35b4d5c99f6a8..c8a4dc12cdc6991d7ccbb19ee08bbd70159ec0cf 100644 (file)
@@ -32,6 +32,7 @@
 #include "log.h"
 #include "sockunion.h" /* for inet_aton () */
 #include "zclient.h"
+#include "routemap.h"
 #include "plist.h"
 #include "sockopt.h"
 #include "bfd.h"
@@ -66,8 +67,6 @@ static struct ospf_master ospf_master;
 struct ospf_master *om;
 
 extern struct zclient *zclient;
-extern struct in_addr router_id_zebra;
-extern struct zebra_privs_t ospfd_privs;
 
 
 static void ospf_remove_vls_through_area(struct ospf *, struct ospf_area *);
@@ -118,12 +117,11 @@ void ospf_router_id_update(struct ospf *ospf)
        else if (ospf->router_id.s_addr != 0)
                router_id = ospf->router_id;
        else
-               router_id = router_id_zebra;
+               router_id = ospf->router_id_zebra;
 
        if (IS_DEBUG_OSPF_EVENT)
                zlog_debug("Router-ID[OLD:%s]: Update to %s",
-                          inet_ntoa(ospf->router_id),
-                          inet_ntoa(router_id_old));
+                          inet_ntoa(ospf->router_id), inet_ntoa(router_id));
 
        if (!IPV4_ADDR_SAME(&router_id_old, &router_id)) {
 
@@ -160,9 +158,9 @@ void ospf_router_id_update(struct ospf *ospf)
                        struct route_node *rn;
                        struct ospf_lsa *lsa;
 
-                       LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa)
-                       if (IS_LSA_SELF(lsa))
-                               ospf_lsa_flush_schedule(ospf, lsa);
+                       LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa)
+                               if (IS_LSA_SELF(lsa))
+                                       ospf_lsa_flush_schedule(ospf, lsa);
                }
 
                ospf->router_id = router_id;
@@ -185,8 +183,7 @@ void ospf_router_id_update(struct ospf *ospf)
                        struct route_node *rn;
                        struct ospf_lsa *lsa;
 
-                       LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa)
-                       {
+                       LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa) {
                                /* AdvRouter and Router ID is the same. */
                                if (IPV4_ADDR_SAME(&lsa->data->adv_router,
                                                   &ospf->router_id)) {
@@ -243,8 +240,9 @@ static struct ospf *ospf_new(u_short instance, const char *name)
                new->name = XSTRDUP(MTYPE_OSPF_TOP, name);
                vrf = vrf_lookup_by_name(new->name);
                if (IS_DEBUG_OSPF_EVENT)
-                       zlog_debug("%s: Create new ospf instance with vrf_name %s vrf_id %d",
-                                  __PRETTY_FUNCTION__, name, new->vrf_id);
+                       zlog_debug(
+                               "%s: Create new ospf instance with vrf_name %s vrf_id %u",
+                               __PRETTY_FUNCTION__, name, new->vrf_id);
                if (vrf)
                        ospf_vrf_link(new, vrf);
        } else {
@@ -310,12 +308,6 @@ static struct ospf *ospf_new(u_short instance, const char *name)
                         new->lsa_refresh_interval, &new->t_lsa_refresher);
        new->lsa_refresher_started = monotime(NULL);
 
-       if ((ospf_sock_init(new)) < 0) {
-               zlog_err(
-                       "ospf_new: fatal error: ospf_sock_init was unable to open "
-                       "a socket");
-               exit(1);
-       }
        if ((new->ibuf = stream_new(OSPF_MAX_PACKET_SIZE + 1)) == NULL) {
                zlog_err(
                        "ospf_new: fatal error: stream_new(%u) failed allocating ibuf",
@@ -323,7 +315,6 @@ static struct ospf *ospf_new(u_short instance, const char *name)
                exit(1);
        }
        new->t_read = NULL;
-       thread_add_read(master, ospf_read, new, new->fd, &new->t_read);
        new->oi_write_q = list_new();
        new->write_oi_count = OSPF_WRITE_INTERFACE_COUNT_DEFAULT;
 
@@ -334,6 +325,16 @@ static struct ospf *ospf_new(u_short instance, const char *name)
 
        QOBJ_REG(new, ospf);
 
+       new->fd = -1;
+       if ((ospf_sock_init(new)) < 0) {
+               if (new->vrf_id != VRF_UNKNOWN)
+                       zlog_warn(
+                               "%s: ospf_sock_init is unable to open a socket",
+                               __func__);
+               return new;
+       }
+       thread_add_read(master, ospf_read, new, new->fd, &new->t_read);
+
        return new;
 }
 
@@ -379,9 +380,10 @@ struct ospf *ospf_lookup_by_inst_name(u_short instance, const char *name)
        struct listnode *node, *nnode;
 
        for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf)) {
-               if ((ospf->instance == instance) &&
-                   ((ospf->name == NULL && name == NULL) ||
-                    (ospf->name && name && strcmp(ospf->name, name) == 0)))
+               if ((ospf->instance == instance)
+                   && ((ospf->name == NULL && name == NULL)
+                       || (ospf->name && name
+                           && strcmp(ospf->name, name) == 0)))
                        return ospf;
        }
        return NULL;
@@ -425,9 +427,10 @@ struct ospf *ospf_get_instance(u_short instance)
                                ospf_router_id_update(ospf);
                        else {
                                if (IS_DEBUG_OSPF_EVENT)
-                                       zlog_debug("%s: ospf VRF (id %d) is not active yet, skip router id update"
-                                                   , __PRETTY_FUNCTION__,
-                                                   ospf->vrf_id);
+                                       zlog_debug(
+                                               "%s: ospf VRF (id %d) is not active yet, skip router id update",
+                                               __PRETTY_FUNCTION__,
+                                               ospf->vrf_id);
                        }
                        ospf_router_id_update(ospf);
                }
@@ -446,7 +449,6 @@ struct ospf *ospf_lookup_by_vrf_id(vrf_id_t vrf_id)
        if (!vrf)
                return NULL;
        return (vrf->info) ? (struct ospf *)vrf->info : NULL;
-
 }
 
 /* It should only be used when processing incoming info update from zebra.
@@ -460,8 +462,8 @@ static struct ospf *ospf_lookup_by_name(const char *vrf_name)
 
        for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf))
                if ((ospf->name == NULL && vrf_name == NULL)
-                   || (ospf->name && vrf_name &&
-                       strcmp(ospf->name, vrf_name) == 0))
+                   || (ospf->name && vrf_name
+                       && strcmp(ospf->name, vrf_name) == 0))
                        return ospf;
        return NULL;
 }
@@ -557,6 +559,20 @@ void ospf_terminate(void)
        for (ALL_LIST_ELEMENTS(om->ospf, node, nnode, ospf))
                ospf_finish(ospf);
 
+       /* Cleanup route maps */
+       route_map_add_hook(NULL);
+       route_map_delete_hook(NULL);
+       route_map_event_hook(NULL);
+       route_map_finish();
+
+       /* reverse prefix_list_init */
+       prefix_list_add_hook(NULL);
+       prefix_list_delete_hook(NULL);
+       prefix_list_reset();
+
+       /* Cleanup vrf info */
+       ospf_vrf_terminate();
+
        /* Deliberately go back up, hopefully to thread scheduler, as
         * One or more ospf_finish()'s may have deferred shutdown to a timer
         * thread
@@ -598,8 +614,9 @@ static void ospf_finish_final(struct ospf *ospf)
 
        ospf_opaque_type11_lsa_term(ospf);
 
-       /* be nice if this worked, but it doesn't */
-       /*ospf_flush_self_originated_lsas_now (ospf);*/
+       ospf_opaque_finish();
+
+       ospf_flush_self_originated_lsas_now(ospf);
 
        /* Unregister redistribution */
        for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
@@ -691,14 +708,15 @@ static void ospf_finish_final(struct ospf *ospf)
        OSPF_TIMER_OFF(ospf->t_read);
        OSPF_TIMER_OFF(ospf->t_write);
        OSPF_TIMER_OFF(ospf->t_opaque_lsa_self);
+       OSPF_TIMER_OFF(ospf->t_sr_update);
 
        close(ospf->fd);
        stream_free(ospf->ibuf);
 
-       LSDB_LOOP(OPAQUE_AS_LSDB(ospf), rn, lsa)
-       ospf_discard_from_db(ospf, ospf->lsdb, lsa);
-       LSDB_LOOP(EXTERNAL_LSDB(ospf), rn, lsa)
-       ospf_discard_from_db(ospf, ospf->lsdb, lsa);
+       LSDB_LOOP (OPAQUE_AS_LSDB(ospf), rn, lsa)
+               ospf_discard_from_db(ospf, ospf->lsdb, lsa);
+       LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa)
+               ospf_discard_from_db(ospf, ospf->lsdb, lsa);
 
        ospf_lsdb_delete_all(ospf->lsdb);
        ospf_lsdb_free(ospf->lsdb);
@@ -744,7 +762,7 @@ static void ospf_finish_final(struct ospf *ospf)
                struct listnode *node;
                struct ospf_external *ext;
 
-               ext_list = om->external[i];
+               ext_list = ospf->external[i];
                if (!ext_list)
                        continue;
 
@@ -832,23 +850,22 @@ static void ospf_area_free(struct ospf_area *area)
        ospf_opaque_type10_lsa_term(area);
 
        /* Free LSDBs. */
-       LSDB_LOOP(ROUTER_LSDB(area), rn, lsa)
-       ospf_discard_from_db(area->ospf, area->lsdb, lsa);
-       LSDB_LOOP(NETWORK_LSDB(area), rn, lsa)
-       ospf_discard_from_db(area->ospf, area->lsdb, lsa);
-       LSDB_LOOP(SUMMARY_LSDB(area), rn, lsa)
-       ospf_discard_from_db(area->ospf, area->lsdb, lsa);
-       LSDB_LOOP(ASBR_SUMMARY_LSDB(area), rn, lsa)
-       ospf_discard_from_db(area->ospf, area->lsdb, lsa);
-
-       LSDB_LOOP(NSSA_LSDB(area), rn, lsa)
-       ospf_discard_from_db(area->ospf, area->lsdb, lsa);
-       LSDB_LOOP(OPAQUE_AREA_LSDB(area), rn, lsa)
-       ospf_discard_from_db(area->ospf, area->lsdb, lsa);
-       LSDB_LOOP(OPAQUE_LINK_LSDB(area), rn, lsa)
-       ospf_discard_from_db(area->ospf, area->lsdb, lsa);
+       LSDB_LOOP (ROUTER_LSDB(area), rn, lsa)
+               ospf_discard_from_db(area->ospf, area->lsdb, lsa);
+       LSDB_LOOP (NETWORK_LSDB(area), rn, lsa)
+               ospf_discard_from_db(area->ospf, area->lsdb, lsa);
+       LSDB_LOOP (SUMMARY_LSDB(area), rn, lsa)
+               ospf_discard_from_db(area->ospf, area->lsdb, lsa);
+       LSDB_LOOP (ASBR_SUMMARY_LSDB(area), rn, lsa)
+               ospf_discard_from_db(area->ospf, area->lsdb, lsa);
+
+       LSDB_LOOP (NSSA_LSDB(area), rn, lsa)
+               ospf_discard_from_db(area->ospf, area->lsdb, lsa);
+       LSDB_LOOP (OPAQUE_AREA_LSDB(area), rn, lsa)
+               ospf_discard_from_db(area->ospf, area->lsdb, lsa);
+       LSDB_LOOP (OPAQUE_LINK_LSDB(area), rn, lsa)
+               ospf_discard_from_db(area->ospf, area->lsdb, lsa);
 
-       ospf_opaque_type10_lsa_term(area);
        ospf_lsdb_delete_all(area->lsdb);
        ospf_lsdb_free(area->lsdb);
 
@@ -973,34 +990,35 @@ static void update_redistributed(struct ospf *ospf, int add_to_ospf)
        struct external_info *ei;
        struct ospf_external *ext;
 
-       if (ospf_is_type_redistributed(ospf, ZEBRA_ROUTE_CONNECT, 0))
-               if ((ext = ospf_external_lookup(ZEBRA_ROUTE_CONNECT, 0))
-                   && EXTERNAL_INFO(ext)) {
+       if (ospf_is_type_redistributed(ospf, ZEBRA_ROUTE_CONNECT, 0)) {
+               ext = ospf_external_lookup(ospf, ZEBRA_ROUTE_CONNECT, 0);
+               if ((ext) && EXTERNAL_INFO(ext)) {
                        for (rn = route_top(EXTERNAL_INFO(ext)); rn;
                             rn = route_next(rn)) {
-                               if ((ei = rn->info) != NULL) {
-                                       if (add_to_ospf) {
-                                               if (ospf_external_info_find_lsa(
-                                                           ospf, &ei->p))
-                                                       if (!ospf_distribute_check_connected(
-                                                                   ospf, ei))
-                                                               ospf_external_lsa_flush(
-                                                                       ospf,
-                                                                       ei->type,
-                                                                       &ei->p,
-                                                                       ei->ifindex /*, ei->nexthop */);
-                                       } else {
-                                               if (!ospf_external_info_find_lsa(
-                                                           ospf, &ei->p))
-                                                       if (ospf_distribute_check_connected(
-                                                                   ospf, ei))
-                                                               ospf_external_lsa_originate(
-                                                                       ospf,
-                                                                       ei);
-                                       }
+                               ei = rn->info;
+                               if (ei == NULL)
+                                       continue;
+
+                               if (add_to_ospf) {
+                                       if (ospf_external_info_find_lsa(ospf,
+                                                                       &ei->p))
+                                               if (!ospf_distribute_check_connected(
+                                                           ospf, ei))
+                                                       ospf_external_lsa_flush(
+                                                               ospf, ei->type,
+                                                               &ei->p,
+                                                               ei->ifindex /*, ei->nexthop */);
+                               } else {
+                                       if (!ospf_external_info_find_lsa(
+                                                   ospf, &ei->p))
+                                               if (ospf_distribute_check_connected(
+                                                           ospf, ei))
+                                                       ospf_external_lsa_originate(
+                                                               ospf, ei);
                                }
                        }
                }
+       }
 }
 
 /* Config network statement related functions. */
@@ -1031,9 +1049,15 @@ int ospf_network_set(struct ospf *ospf, struct prefix_ipv4 *p,
 
        rn = route_node_get(ospf->networks, (struct prefix *)p);
        if (rn->info) {
-               /* There is already same network statement. */
+               network = rn->info;
                route_unlock_node(rn);
-               return 0;
+
+               if (IPV4_ADDR_SAME(&area_id, &network->area_id)) {
+                       return 1;
+               } else {
+                       /* There is already same network statement. */
+                       return 0;
+               }
        }
 
        rn->info = network = ospf_network_new(area_id);
@@ -1076,10 +1100,10 @@ int ospf_network_unset(struct ospf *ospf, struct prefix_ipv4 *p,
        /* Find interfaces that are not configured already.  */
        for (ALL_LIST_ELEMENTS(ospf->oiflist, node, nnode, oi)) {
 
-         if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
-           continue;
+               if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
+                       continue;
 
-         ospf_network_run_subnet(ospf, oi->connected, NULL, NULL);
+               ospf_network_run_subnet(ospf, oi->connected, NULL, NULL);
        }
 
        /* Update connected redistribute. */
@@ -1297,10 +1321,11 @@ void ospf_if_update(struct ospf *ospf, struct interface *ifp)
                return;
 
        if (IS_DEBUG_OSPF_EVENT)
-               zlog_debug("%s: interface %s ifp->vrf_id %u ospf vrf %s vrf_id %u router_id %s",
-                          __PRETTY_FUNCTION__, ifp->name, ifp->vrf_id,
-                          ospf_vrf_id_to_name(ospf->vrf_id), ospf->vrf_id,
-                          inet_ntoa(ospf->router_id));
+               zlog_debug(
+                       "%s: interface %s ifp->vrf_id %u ospf vrf %s vrf_id %u router_id %s",
+                       __PRETTY_FUNCTION__, ifp->name, ifp->vrf_id,
+                       ospf_vrf_id_to_name(ospf->vrf_id), ospf->vrf_id,
+                       inet_ntoa(ospf->router_id));
 
        /* OSPF must be ready. */
        if (!ospf_is_ready(ospf))
@@ -2008,7 +2033,7 @@ void ospf_vrf_unlink(struct ospf *ospf, struct vrf *vrf)
 static int ospf_vrf_new(struct vrf *vrf)
 {
        if (IS_DEBUG_OSPF_EVENT)
-               zlog_debug("%s: VRF Created: %s(%d)", __PRETTY_FUNCTION__,
+               zlog_debug("%s: VRF Created: %s(%u)", __PRETTY_FUNCTION__,
                           vrf->name, vrf->vrf_id);
 
        return 0;
@@ -2018,7 +2043,7 @@ static int ospf_vrf_new(struct vrf *vrf)
 static int ospf_vrf_delete(struct vrf *vrf)
 {
        if (IS_DEBUG_OSPF_EVENT)
-               zlog_debug("%s: VRF Deletion: %s(%d)", __PRETTY_FUNCTION__,
+               zlog_debug("%s: VRF Deletion: %s(%u)", __PRETTY_FUNCTION__,
                           vrf->name, vrf->vrf_id);
 
        return 0;
@@ -2028,11 +2053,12 @@ static int ospf_vrf_delete(struct vrf *vrf)
 static int ospf_vrf_enable(struct vrf *vrf)
 {
        struct ospf *ospf = NULL;
-       vrf_id_t old_vrf_id = VRF_DEFAULT;
+       vrf_id_t old_vrf_id;
+       int ret = 0;
 
        if (IS_DEBUG_OSPF_EVENT)
-               zlog_debug("%s: VRF %s id %d enabled",
-                          __PRETTY_FUNCTION__, vrf->name, vrf->vrf_id);
+               zlog_debug("%s: VRF %s id %u enabled", __PRETTY_FUNCTION__,
+                          vrf->name, vrf->vrf_id);
 
        ospf = ospf_lookup_by_name(vrf->name);
        if (ospf) {
@@ -2040,23 +2066,29 @@ static int ospf_vrf_enable(struct vrf *vrf)
                /* We have instance configured, link to VRF and make it "up". */
                ospf_vrf_link(ospf, vrf);
                if (IS_DEBUG_OSPF_EVENT)
-                       zlog_debug("%s: ospf linked to vrf %s vrf_id %d (old id %d)",
-                                  __PRETTY_FUNCTION__, vrf->name, ospf->vrf_id,
-                                  old_vrf_id);
+                       zlog_debug(
+                               "%s: ospf linked to vrf %s vrf_id %u (old id %u)",
+                               __PRETTY_FUNCTION__, vrf->name, ospf->vrf_id,
+                               old_vrf_id);
 
                if (old_vrf_id != ospf->vrf_id) {
                        if (ospfd_privs.change(ZPRIVS_RAISE)) {
-                               zlog_err("ospf_sock_init: could not raise privs, %s",
-                                        safe_strerror(errno));
+                               zlog_err(
+                                       "ospf_sock_init: could not raise privs, %s",
+                                       safe_strerror(errno));
                        }
-                       if (ospf_bind_vrfdevice(ospf, ospf->fd) < 0)
-                               return 0;
+                       ret = ospf_sock_init(ospf);
                        if (ospfd_privs.change(ZPRIVS_LOWER)) {
-                               zlog_err("ospf_sock_init: could not lower privs, %s",
-                                        safe_strerror(errno));
+                               zlog_err(
+                                       "ospf_sock_init: could not lower privs, %s",
+                                       safe_strerror(errno));
                        }
-
+                       if (ret < 0 || ospf->fd <= 0)
+                               return 0;
+                       thread_add_read(master, ospf_read, ospf, ospf->fd,
+                                       &ospf->t_read);
                        ospf->oi_running = 1;
+                       ospf_zebra_vrf_register(ospf);
                        ospf_router_id_update(ospf);
                }
        }
@@ -2074,8 +2106,8 @@ static int ospf_vrf_disable(struct vrf *vrf)
                return 0;
 
        if (IS_DEBUG_OSPF_EVENT)
-               zlog_debug("%s: VRF %s id %d disabled.",
-                          __PRETTY_FUNCTION__, vrf->name, vrf->vrf_id);
+               zlog_debug("%s: VRF %s id %d disabled.", __PRETTY_FUNCTION__,
+                          vrf->name, vrf->vrf_id);
 
        ospf = ospf_lookup_by_name(vrf->name);
        if (ospf) {
@@ -2088,7 +2120,10 @@ static int ospf_vrf_disable(struct vrf *vrf)
                ospf->oi_running = 0;
                if (IS_DEBUG_OSPF_EVENT)
                        zlog_debug("%s: ospf old_vrf_id %d unlinked",
-                                   __PRETTY_FUNCTION__, old_vrf_id);
+                                  __PRETTY_FUNCTION__, old_vrf_id);
+               thread_cancel(ospf->t_read);
+               close(ospf->fd);
+               ospf->fd = -1;
        }
 
        /* Note: This is a callback, the VRF will be deleted by the caller. */
@@ -2097,8 +2132,8 @@ static int ospf_vrf_disable(struct vrf *vrf)
 
 void ospf_vrf_init(void)
 {
-       vrf_init(ospf_vrf_new, ospf_vrf_enable,
-                ospf_vrf_disable, ospf_vrf_delete);
+       vrf_init(ospf_vrf_new, ospf_vrf_enable, ospf_vrf_disable,
+                ospf_vrf_delete);
 }
 
 void ospf_vrf_terminate(void)