]> git.proxmox.com Git - mirror_frr.git/blobdiff - eigrpd/eigrp_interface.c
zebra: Allow ns delete to happen after under/over flow checks
[mirror_frr.git] / eigrpd / eigrp_interface.c
index f2512eadade61c18c7656dd32c8aebb7c7848c6a..e450c7d999322c23a718bda5c2f30b690d8c87e9 100644 (file)
 #include "eigrpd/eigrp_memory.h"
 #include "eigrpd/eigrp_fsm.h"
 
-static void eigrp_delete_from_if(struct interface *, struct eigrp_interface *);
-
-static void eigrp_add_to_if(struct interface *ifp, struct eigrp_interface *ei)
-{
-       struct route_node *rn;
-       struct prefix p;
-
-       p = *ei->address;
-       p.prefixlen = IPV4_MAX_PREFIXLEN;
-
-       rn = route_node_get(IF_OIFS(ifp), &p);
-       /* rn->info should either be NULL or equal to this ei
-        * as route_node_get may return an existing node
-        */
-       assert(!rn->info || rn->info == ei);
-       rn->info = ei;
-}
-
 struct eigrp_interface *eigrp_if_new(struct eigrp *eigrp, struct interface *ifp,
                                     struct prefix *p)
 {
-       struct eigrp_interface *ei;
+       struct eigrp_interface *ei = ifp->info;
        int i;
 
-       if ((ei = eigrp_if_table_lookup(ifp, p)) == NULL) {
-               ei = XCALLOC(MTYPE_EIGRP_IF, sizeof(struct eigrp_interface));
-               memset(ei, 0, sizeof(struct eigrp_interface));
-       } else
+       if (ei)
                return ei;
 
+       ei = XCALLOC(MTYPE_EIGRP_IF, sizeof(struct eigrp_interface));
+
        /* Set zebra interface pointer. */
        ei->ifp = ifp;
        ei->address = p;
 
-       eigrp_add_to_if(ifp, ei);
+       ifp->info = ei;
        listnode_add(eigrp->eiflist, ei);
 
        ei->type = EIGRP_IFTYPE_BROADCAST;
@@ -106,39 +87,32 @@ struct eigrp_interface *eigrp_if_new(struct eigrp *eigrp, struct interface *ifp,
                ei->routemap[i] = NULL;
        }
 
-       return ei;
-}
-
-/* lookup ei for specified prefix/ifp */
-struct eigrp_interface *eigrp_if_table_lookup(struct interface *ifp,
-                                             struct prefix *prefix)
-{
-       struct prefix p;
-       struct route_node *rn;
-       struct eigrp_interface *rninfo = NULL;
+       ei->eigrp = eigrp;
 
-       p = *prefix;
-       p.prefixlen = IPV4_MAX_PREFIXLEN;
+       ei->params.v_hello = EIGRP_HELLO_INTERVAL_DEFAULT;
+       ei->params.v_wait = EIGRP_HOLD_INTERVAL_DEFAULT;
+       ei->params.bandwidth = EIGRP_BANDWIDTH_DEFAULT;
+       ei->params.delay = EIGRP_DELAY_DEFAULT;
+       ei->params.reliability = EIGRP_RELIABILITY_DEFAULT;
+       ei->params.load = EIGRP_LOAD_DEFAULT;
+       ei->params.auth_type = EIGRP_AUTH_TYPE_NONE;
+       ei->params.auth_keychain = NULL;
 
-       /* route_node_get implicitly locks */
-       if ((rn = route_node_lookup(IF_OIFS(ifp), &p))) {
-               rninfo = (struct eigrp_interface *)rn->info;
-               route_unlock_node(rn);
-       }
-
-       return rninfo;
+       return ei;
 }
 
 int eigrp_if_delete_hook(struct interface *ifp)
 {
-       struct route_node *rn;
+       struct eigrp_interface *ei = ifp->info;
+       struct eigrp *eigrp;
 
-       route_table_finish(IF_OIFS(ifp));
+       if (!ei)
+               return 0;
 
-       for (rn = route_top(IF_OIFS_PARAMS(ifp)); rn; rn = route_next(rn))
-               if (rn->info)
-                       eigrp_del_if_params(rn->info);
-       route_table_finish(IF_OIFS_PARAMS(ifp));
+       list_delete(&ei->nbrs);
+
+       eigrp = ei->eigrp;
+       listnode_delete(eigrp->eiflist, ei);
 
        XFREE(MTYPE_EIGRP_IF_INFO, ifp->info);
        ifp->info = NULL;
@@ -151,95 +125,15 @@ struct list *eigrp_iflist;
 void eigrp_if_init()
 {
        /* Initialize Zebra interface data structure. */
-       hook_register_prio(if_add, 0, eigrp_if_new_hook);
+       // hook_register_prio(if_add, 0, eigrp_if_new);
        hook_register_prio(if_del, 0, eigrp_if_delete_hook);
 }
 
-int eigrp_if_new_hook(struct interface *ifp)
-{
-       int rc = 0;
-
-       ifp->info = XCALLOC(MTYPE_EIGRP_IF_INFO, sizeof(struct eigrp_if_info));
-
-       IF_OIFS(ifp) = route_table_init();
-       IF_OIFS_PARAMS(ifp) = route_table_init();
-
-       IF_DEF_PARAMS(ifp) = eigrp_new_if_params();
-
-       SET_IF_PARAM(IF_DEF_PARAMS(ifp), v_hello);
-       IF_DEF_PARAMS(ifp)->v_hello = (u_int32_t)EIGRP_HELLO_INTERVAL_DEFAULT;
-
-       SET_IF_PARAM(IF_DEF_PARAMS(ifp), v_wait);
-       IF_DEF_PARAMS(ifp)->v_wait = (u_int16_t)EIGRP_HOLD_INTERVAL_DEFAULT;
-
-       SET_IF_PARAM(IF_DEF_PARAMS(ifp), bandwidth);
-       IF_DEF_PARAMS(ifp)->bandwidth = (u_int32_t)EIGRP_BANDWIDTH_DEFAULT;
-
-       SET_IF_PARAM(IF_DEF_PARAMS(ifp), delay);
-       IF_DEF_PARAMS(ifp)->delay = (u_int32_t)EIGRP_DELAY_DEFAULT;
-
-       SET_IF_PARAM(IF_DEF_PARAMS(ifp), reliability);
-       IF_DEF_PARAMS(ifp)->reliability = (u_char)EIGRP_RELIABILITY_DEFAULT;
-
-       SET_IF_PARAM(IF_DEF_PARAMS(ifp), load);
-       IF_DEF_PARAMS(ifp)->load = (u_char)EIGRP_LOAD_DEFAULT;
-
-       SET_IF_PARAM(IF_DEF_PARAMS(ifp), auth_type);
-       IF_DEF_PARAMS(ifp)->auth_type = EIGRP_AUTH_TYPE_NONE;
-
-       SET_IF_PARAM(IF_DEF_PARAMS(ifp), auth_keychain);
-       IF_DEF_PARAMS(ifp)->auth_keychain = NULL;
-
-       return rc;
-}
-
-struct eigrp_if_params *eigrp_new_if_params(void)
-{
-       struct eigrp_if_params *eip;
-
-       eip = XCALLOC(MTYPE_EIGRP_IF_PARAMS, sizeof(struct eigrp_if_params));
-       if (!eip)
-               return NULL;
-
-       UNSET_IF_PARAM(eip, passive_interface);
-       UNSET_IF_PARAM(eip, v_hello);
-       UNSET_IF_PARAM(eip, v_wait);
-       UNSET_IF_PARAM(eip, bandwidth);
-       UNSET_IF_PARAM(eip, delay);
-       UNSET_IF_PARAM(eip, reliability);
-       UNSET_IF_PARAM(eip, load);
-       UNSET_IF_PARAM(eip, auth_keychain);
-       UNSET_IF_PARAM(eip, auth_type);
-
-       return eip;
-}
 
 void eigrp_del_if_params(struct eigrp_if_params *eip)
 {
        if (eip->auth_keychain)
                free(eip->auth_keychain);
-
-       XFREE(MTYPE_EIGRP_IF_PARAMS, eip);
-}
-
-struct eigrp_if_params *eigrp_lookup_if_params(struct interface *ifp,
-                                              struct in_addr addr)
-{
-       struct prefix p;
-       struct route_node *rn;
-
-       p.family = AF_INET;
-       p.prefixlen = IPV4_MAX_PREFIXLEN;
-       p.u.prefix4 = addr;
-
-       rn = route_node_lookup(IF_OIFS_PARAMS(ifp), &p);
-
-       if (rn) {
-               route_unlock_node(rn);
-               return rn->info;
-       }
-
-       return NULL;
 }
 
 int eigrp_if_up(struct eigrp_interface *ei)
@@ -265,11 +159,10 @@ int eigrp_if_up(struct eigrp_interface *ei)
        thread_add_event(master, eigrp_hello_timer, ei, (1), NULL);
 
        /*Prepare metrics*/
-       metric.bandwidth =
-               eigrp_bandwidth_to_scaled(EIGRP_IF_PARAM(ei, bandwidth));
-       metric.delay = eigrp_delay_to_scaled(EIGRP_IF_PARAM(ei, delay));
-       metric.load = EIGRP_IF_PARAM(ei, load);
-       metric.reliability = EIGRP_IF_PARAM(ei, reliability);
+       metric.bandwidth = eigrp_bandwidth_to_scaled(ei->params.bandwidth);
+       metric.delay = eigrp_delay_to_scaled(ei->params.delay);
+       metric.load = ei->params.load;
+       metric.reliability = ei->params.reliability;
        metric.mtu[0] = 0xDC;
        metric.mtu[1] = 0x05;
        metric.mtu[2] = 0x00;
@@ -290,9 +183,7 @@ int eigrp_if_up(struct eigrp_interface *ei)
 
        struct prefix dest_addr;
 
-       dest_addr.family = AF_INET;
-       dest_addr.u.prefix4 = ei->connected->address->u.prefix4;
-       dest_addr.prefixlen = ei->connected->address->prefixlen;
+       dest_addr = *ei->address;
        apply_mask(&dest_addr);
        pe = eigrp_topology_table_lookup_ipv4(eigrp->topology_table,
                                              &dest_addr);
@@ -387,38 +278,47 @@ void eigrp_if_stream_unset(struct eigrp_interface *ei)
        }
 }
 
+bool eigrp_if_is_passive(struct eigrp_interface *ei)
+{
+       if (ei->params.passive_interface == EIGRP_IF_ACTIVE)
+               return false;
+
+       if (ei->eigrp->passive_interface_default == EIGRP_IF_ACTIVE)
+               return false;
+
+       return true;
+}
+
 void eigrp_if_set_multicast(struct eigrp_interface *ei)
 {
-       if ((EIGRP_IF_PASSIVE_STATUS(ei) == EIGRP_IF_ACTIVE)) {
+       if (!eigrp_if_is_passive(ei)) {
                /* The interface should belong to the EIGRP-all-routers group.
                 */
-               if (!EI_MEMBER_CHECK(ei, MEMBER_ALLROUTERS)
+               if (!ei->member_allrouters
                    && (eigrp_if_add_allspfrouters(ei->eigrp, ei->address,
                                                   ei->ifp->ifindex)
                        >= 0))
                        /* Set the flag only if the system call to join
                         * succeeded. */
-                       EI_MEMBER_JOINED(ei, MEMBER_ALLROUTERS);
+                       ei->member_allrouters = true;
        } else {
                /* The interface should NOT belong to the EIGRP-all-routers
                 * group. */
-               if (EI_MEMBER_CHECK(ei, MEMBER_ALLROUTERS)) {
+               if (ei->member_allrouters) {
                        /* Only actually drop if this is the last reference */
-                       if (EI_MEMBER_COUNT(ei, MEMBER_ALLROUTERS) == 1)
-                               eigrp_if_drop_allspfrouters(ei->eigrp,
-                                                           ei->address,
-                                                           ei->ifp->ifindex);
+                       eigrp_if_drop_allspfrouters(ei->eigrp, ei->address,
+                                                   ei->ifp->ifindex);
                        /* Unset the flag regardless of whether the system call
                           to leave
                           the group succeeded, since it's much safer to assume
                           that
                           we are not a member. */
-                       EI_MEMBER_LEFT(ei, MEMBER_ALLROUTERS);
+                       ei->member_allrouters = false;
                }
        }
 }
 
-u_char eigrp_default_iftype(struct interface *ifp)
+uint8_t eigrp_default_iftype(struct interface *ifp)
 {
        if (if_is_pointopoint(ifp))
                return EIGRP_IFTYPE_POINTOPOINT;
@@ -434,12 +334,15 @@ void eigrp_if_free(struct eigrp_interface *ei, int source)
        struct eigrp_prefix_entry *pe;
        struct eigrp *eigrp = eigrp_lookup();
 
+       if (!eigrp)
+               return;
+
        if (source == INTERFACE_DOWN_BY_VTY) {
                THREAD_OFF(ei->t_hello);
                eigrp_hello_send(ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL);
        }
 
-       dest_addr = *ei->connected->address;
+       dest_addr = *ei->address;
        apply_mask(&dest_addr);
        pe = eigrp_topology_table_lookup_ipv4(eigrp->topology_table,
                                              &dest_addr);
@@ -448,48 +351,21 @@ void eigrp_if_free(struct eigrp_interface *ei, int source)
 
        eigrp_if_down(ei);
 
-       list_delete(ei->nbrs);
-       eigrp_delete_from_if(ei->ifp, ei);
+       list_delete(&ei->nbrs);
        listnode_delete(ei->eigrp->eiflist, ei);
-
-       thread_cancel_event(master, ei);
-
-       memset(ei, 0, sizeof(*ei));
-       XFREE(MTYPE_EIGRP_IF, ei);
-}
-
-static void eigrp_delete_from_if(struct interface *ifp,
-                                struct eigrp_interface *ei)
-{
-       struct route_node *rn;
-       struct prefix p;
-
-       p = *ei->address;
-       p.prefixlen = IPV4_MAX_PREFIXLEN;
-
-       rn = route_node_lookup(IF_OIFS(ei->ifp), &p);
-       assert(rn);
-       assert(rn->info);
-       rn->info = NULL;
-       route_unlock_node(rn);
-       route_unlock_node(rn);
 }
 
 /* Simulate down/up on the interface.  This is needed, for example, when
    the MTU changes. */
 void eigrp_if_reset(struct interface *ifp)
 {
-       struct route_node *rn;
+       struct eigrp_interface *ei = ifp->info;
 
-       for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
-               struct eigrp_interface *ei;
+       if (!ei)
+               return;
 
-               if ((ei = rn->info) == NULL)
-                       continue;
-
-               eigrp_if_down(ei);
-               eigrp_if_up(ei);
-       }
+       eigrp_if_down(ei);
+       eigrp_if_up(ei);
 }
 
 struct eigrp_interface *eigrp_if_lookup_by_local_addr(struct eigrp *eigrp,
@@ -538,67 +414,32 @@ struct eigrp_interface *eigrp_if_lookup_by_name(struct eigrp *eigrp,
        return NULL;
 }
 
-/* determine receiving interface by ifp and source address */
-struct eigrp_interface *eigrp_if_lookup_recv_if(struct eigrp *eigrp,
-                                               struct in_addr src,
-                                               struct interface *ifp)
-{
-       struct route_node *rn;
-       struct prefix addr;
-       struct eigrp_interface *ei, *match;
-
-       addr.family = AF_INET;
-       addr.u.prefix4 = src;
-       addr.prefixlen = IPV4_MAX_BITLEN;
-
-       match = NULL;
-
-       for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
-               ei = rn->info;
-
-               if (!ei) /* oi can be NULL for PtP aliases */
-                       continue;
-
-               if (if_is_loopback(ei->ifp))
-                       continue;
-
-               if (prefix_match(CONNECTED_PREFIX(ei->connected),
-                                &addr)) {
-                       if ((match == NULL) || (match->address->prefixlen
-                                               < ei->address->prefixlen))
-                               match = ei;
-               }
-       }
-
-       return match;
-}
-
-u_int32_t eigrp_bandwidth_to_scaled(u_int32_t bandwidth)
+uint32_t eigrp_bandwidth_to_scaled(uint32_t bandwidth)
 {
        uint64_t temp_bandwidth = (256ull * 10000000) / bandwidth;
 
        temp_bandwidth = temp_bandwidth < EIGRP_MAX_METRIC ? temp_bandwidth
                                                           : EIGRP_MAX_METRIC;
 
-       return (u_int32_t)temp_bandwidth;
+       return (uint32_t)temp_bandwidth;
 }
 
-u_int32_t eigrp_scaled_to_bandwidth(u_int32_t scaled)
+uint32_t eigrp_scaled_to_bandwidth(uint32_t scaled)
 {
        uint64_t temp_scaled = scaled * (256ull * 10000000);
 
        temp_scaled =
                temp_scaled < EIGRP_MAX_METRIC ? temp_scaled : EIGRP_MAX_METRIC;
 
-       return (u_int32_t)temp_scaled;
+       return (uint32_t)temp_scaled;
 }
 
-u_int32_t eigrp_delay_to_scaled(u_int32_t delay)
+uint32_t eigrp_delay_to_scaled(uint32_t delay)
 {
        return delay * 256;
 }
 
-u_int32_t eigrp_scaled_to_delay(u_int32_t scaled)
+uint32_t eigrp_scaled_to_delay(uint32_t scaled)
 {
        return scaled / 256;
 }