frr/ospfd/ospf_interface.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

1515 lines
36 KiB
C
Raw Normal View History

2002-12-13 21:15:29 +01:00
/*
* OSPF Interface functions.
* Copyright (C) 1999, 2000 Toshiaki Takada
*
* This file is part of GNU Zebra.
*
2002-12-13 21:15:29 +01:00
* GNU Zebra 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.
*
* GNU Zebra is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; see the file COPYING; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2002-12-13 21:15:29 +01:00
*/
#include <zebra.h>
#include "thread.h"
#include "linklist.h"
#include "prefix.h"
#include "if.h"
#include "table.h"
#include "memory.h"
#include "command.h"
#include "stream.h"
#include "log.h"
#include "zclient.h"
#include "bfd.h"
#include "ldp_sync.h"
2002-12-13 21:15:29 +01:00
#include "ospfd/ospfd.h"
#include "ospfd/ospf_bfd.h"
2002-12-13 21:15:29 +01:00
#include "ospfd/ospf_spf.h"
#include "ospfd/ospf_interface.h"
#include "ospfd/ospf_ism.h"
#include "ospfd/ospf_asbr.h"
#include "ospfd/ospf_lsa.h"
#include "ospfd/ospf_lsdb.h"
#include "ospfd/ospf_neighbor.h"
#include "ospfd/ospf_nsm.h"
#include "ospfd/ospf_packet.h"
#include "ospfd/ospf_abr.h"
#include "ospfd/ospf_network.h"
#include "ospfd/ospf_dump.h"
#include "ospfd/ospf_ldp_sync.h"
#include "ospfd/ospf_route.h"
#include "ospfd/ospf_te.h"
2002-12-13 21:15:29 +01:00
DEFINE_QOBJ_TYPE(ospf_interface);
DEFINE_HOOK(ospf_vl_add, (struct ospf_vl_data * vd), (vd));
DEFINE_HOOK(ospf_vl_delete, (struct ospf_vl_data * vd), (vd));
DEFINE_HOOK(ospf_if_update, (struct interface * ifp), (ifp));
DEFINE_HOOK(ospf_if_delete, (struct interface * ifp), (ifp));
int ospf_interface_neighbor_count(struct ospf_interface *oi)
{
int count = 0;
struct route_node *rn;
struct ospf_neighbor *nbr = NULL;
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
nbr = rn->info;
if (nbr) {
/* Do not show myself. */
if (nbr == oi->nbr_self)
continue;
/* Down state is not shown. */
if (nbr->state == NSM_Down)
continue;
count++;
}
}
return count;
}
2002-12-13 21:15:29 +01:00
int ospf_if_get_output_cost(struct ospf_interface *oi)
{
/* If all else fails, use default OSPF cost */
uint32_t cost;
uint32_t bw, refbw;
/* if LDP-IGP Sync is running on interface set cost so interface
* is used only as last resort
*/
if (ldp_sync_if_is_enabled(IF_DEF_PARAMS(oi->ifp)->ldp_sync_info))
return (LDP_OSPF_LSINFINITY);
/* ifp speed and bw can be 0 in some platforms, use ospf default bw
if bw is configured under interface it would be used.
*/
if (!oi->ifp->bandwidth && oi->ifp->speed)
bw = oi->ifp->speed;
else
bw = oi->ifp->bandwidth ? oi->ifp->bandwidth
: OSPF_DEFAULT_BANDWIDTH;
refbw = oi->ospf->ref_bandwidth;
/* A specified ip ospf cost overrides a calculated one. */
2002-12-13 21:15:29 +01:00
if (OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS(oi->ifp), output_cost_cmd)
|| OSPF_IF_PARAM_CONFIGURED(oi->params, output_cost_cmd))
cost = OSPF_IF_PARAM(oi, output_cost_cmd);
/* See if a cost can be calculated from the zebra processes
interface bandwidth field. */
else {
cost = (uint32_t)((double)refbw / (double)bw + (double)0.5);
2002-12-13 21:15:29 +01:00
if (cost < 1)
cost = 1;
else if (cost > 65535)
cost = 65535;
}
2002-12-13 21:15:29 +01:00
return cost;
}
void ospf_if_recalculate_output_cost(struct interface *ifp)
{
uint32_t newcost;
2002-12-13 21:15:29 +01:00
struct route_node *rn;
2002-12-13 21:15:29 +01:00
for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
struct ospf_interface *oi;
2002-12-13 21:15:29 +01:00
if ((oi = rn->info) == NULL)
continue;
2002-12-13 21:15:29 +01:00
newcost = ospf_if_get_output_cost(oi);
2002-12-13 21:15:29 +01:00
/* Is actual output cost changed? */
if (oi->output_cost != newcost) {
oi->output_cost = newcost;
ospf_router_lsa_update_area(oi->area);
}
2002-12-13 21:15:29 +01:00
}
}
/* Simulate down/up on the interface. This is needed, for example, when
the MTU changes. */
void ospf_if_reset(struct interface *ifp)
{
struct route_node *rn;
for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
struct ospf_interface *oi;
if ((oi = rn->info) == NULL)
continue;
ospf_if_down(oi);
ospf_if_up(oi);
}
}
2002-12-13 21:15:29 +01:00
void ospf_if_reset_variables(struct ospf_interface *oi)
{
/* Set default values. */
/* don't clear this flag. oi->flag = OSPF_IF_DISABLE; */
if (oi->vl_data)
oi->type = OSPF_IFTYPE_VIRTUALLINK;
else
/* preserve network-type */
if (oi->type != OSPF_IFTYPE_NBMA)
oi->type = OSPF_IFTYPE_BROADCAST;
oi->state = ISM_Down;
oi->crypt_seqnum = 0;
/* This must be short, (less than RxmtInterval)
- RFC 2328 Section 13.5 para 3. Set to 1 second to avoid Acks being
held back for too long - MAG */
oi->v_ls_ack = 1;
}
/* lookup oi for specified prefix/ifp */
struct ospf_interface *ospf_if_table_lookup(struct interface *ifp,
struct prefix *prefix)
{
struct prefix p;
struct route_node *rn;
struct ospf_interface *rninfo = NULL;
p = *prefix;
p.prefixlen = IPV4_MAX_BITLEN;
/* route_node_get implicitely locks */
2005-10-21 Paul Jakma <paul.jakma@sun.com> * (general) OSPF fast, sub-second hello and 1s dead-interval support. A warning fix. Millisec support for ospf_timer_dump. Change auto-cost ref-bandwidth to add a comment to write out of config, rather than printing annoying messages to vty on startup. * ospf_dump.c: (ospf_timer_dump) Print out milliseconds too. Callers typically specify a length of 9, so most see millisecs unless they specify the additional length. * ospf_interface.h: (struct ospf_interface) new interface param, fast_hello. * ospf_interface.c: (ospf_if_table_lookup) add brackets, gcc warning fix. (ospf_new_if_params) Initialise fast_hello param. (ospf_free_if_params) Check whether fast_hello is configured. (ospf_if_new_hook) set fast_hello to default. * ospf_ism.h: Wrap OSPF_ISM_TIMER_ON inside do {} while (0) to prevent funny side-effects from its if statement when this macro is used conditionally by other macros. (OSPF_ISM_TIMER_MSEC_ON) new macro, set in milliseconds. (OSPF_HELLO_TIMER_ON) new macro to set hello timer according to whether fast_hello is set. * ospf_ism.c: Update all setting of the hello timer to use either OSPF_ISM_TIMER_MSEC_ON or OSPF_HELLO_TIMER_ON. The former is used when hello is to be sent immediately. * ospf_nsm.c: ditto * ospf_packet.c: (ospf_hello) hello-interval is not checked for mismatch if fast_hello is set. (ospf_read) Annoying nit, fix "no ospf_interface" to be debug rather than a warning, as it can be perfectly normal to receive packets when logical subnets are used. (ospf_make_hello) Set hello-interval to 0 if fast-hellos are configured. * ospf_vty.c: (ospf_auto_cost_reference_bandwidth) annoying nit, don't vty_out if this command is given, it gets tired quick. (show_ip_ospf_interface_sub) Print the hello-interval according to whether fast-hello is set or not. Print the extra 5 millisec characters from (ospf_timer_dump) if fast-hello is configured. (ospf_vty_dead_interval_set) new function, common to all forms of dead-interval command, to set dead-interval and fast-hello correctly. If a dead-interval is given, unset fast-hello, else if a hello-multiplier is set, set dead-interval to 1 and fast-hello to given multiplier. (ip_ospf_dead_interval_addr_cmd) use ospf_vty_dead_interval_set(). (ip_ospf_dead_interval_minimal_addr_cmd) ditto. (no_ip_ospf_dead_interval) Unset fast-hello. (no_ip_ospf_hello_interval) Bug-fix, unset of hello-interval should set it to OSPF_HELLO_INTERVAL_DEFAULT, not OSPF_ROUTER_DEAD_INTERVAL_DEFAULT. (config_write_interface) Write out fast-hello. (ospf_config_write) Write a comment about "auto-cost reference-bandwidth" having to be equal on all routers. Hopefully just as noticeable as old practice of writing to vty, but less annoying. (ospf_vty_if_init) install the two new dead-interval commands. * ospfd.h: Add defines for OSPF_ROUTER_DEAD_INTERVAL_MINIMAL and OSPF_FAST_HELLO_DEFAULT.
2005-10-21 02:45:17 +02:00
if ((rn = route_node_lookup(IF_OIFS(ifp), &p))) {
rninfo = (struct ospf_interface *)rn->info;
route_unlock_node(rn);
}
return rninfo;
}
2002-12-13 21:15:29 +01:00
static void ospf_add_to_if(struct interface *ifp, struct ospf_interface *oi)
{
struct route_node *rn;
struct prefix p;
2002-12-13 21:15:29 +01:00
p = *oi->address;
p.prefixlen = IPV4_MAX_BITLEN;
apply_mask(&p);
2002-12-13 21:15:29 +01:00
rn = route_node_get(IF_OIFS(ifp), &p);
/* rn->info should either be NULL or equal to this oi
* as route_node_get may return an existing node
*/
assert(!rn->info || rn->info == oi);
2002-12-13 21:15:29 +01:00
rn->info = oi;
}
static void ospf_delete_from_if(struct interface *ifp,
struct ospf_interface *oi)
{
struct route_node *rn;
struct prefix p;
2002-12-13 21:15:29 +01:00
p = *oi->address;
p.prefixlen = IPV4_MAX_BITLEN;
2002-12-13 21:15:29 +01:00
rn = route_node_lookup(IF_OIFS(oi->ifp), &p);
assert(rn);
assert(rn->info);
rn->info = NULL;
route_unlock_node(rn);
route_unlock_node(rn);
}
struct ospf_interface *ospf_if_new(struct ospf *ospf, struct interface *ifp,
struct prefix *p)
2002-12-13 21:15:29 +01:00
{
struct ospf_interface *oi;
oi = ospf_if_table_lookup(ifp, p);
if (oi)
return oi;
oi = XCALLOC(MTYPE_OSPF_IF, sizeof(struct ospf_interface));
oi->obuf = ospf_fifo_new();
2002-12-13 21:15:29 +01:00
/* Set zebra interface pointer. */
oi->ifp = ifp;
oi->address = p;
2002-12-13 21:15:29 +01:00
ospf_add_to_if(ifp, oi);
listnode_add(ospf->oiflist, oi);
2002-12-13 21:15:29 +01:00
/* Initialize neighbor list. */
oi->nbrs = route_table_init();
2002-12-13 21:15:29 +01:00
/* Initialize static neighbor list. */
oi->nbr_nbma = list_new();
2002-12-13 21:15:29 +01:00
/* Initialize Link State Acknowledgment list. */
oi->ls_ack = list_new();
oi->ls_ack_direct.ls_ack = list_new();
2002-12-13 21:15:29 +01:00
/* Set default values. */
ospf_if_reset_variables(oi);
ospfd: fix - correct neighbor index on changing/p2p/virtual links ospfd keeps a list of neighbor routers for each configured interface. This list is indexed using the neighbor router id in case of point-to-point and virtual link types, otherwise the list is indexed using the neighbor's source IP (RFC 2328, page 96). The router adds itself as a "pseudo" neighbor on each link, and also keeps a pointer called (nbr_self) to the neighbor structure. This takes place when the interface is first configured. Currently ospfd adds this pseudo neighbor before the link parameters are fully configure, including whether the link type is point-to-point or virtual link. This causes the pseudo neighbor to be always indexed using the source IP address regardless of th link type. For point-to-point and virtual links, this causes the lookup for the pseudo neighbor to always fail because the lookup is done using the router id whereas the neighbor was added using its source IP address. This becomes really problematic if there is a state change that requires a rebuild of nbr_self, changing the router id for example. When resetting nbr_self, the router first tries to remove the pseudo neighbor form its neighbor list on each link by looking it up and resetting any references to it before freeing the neighbor structure. since the lookup fails to retrieve any references in the case of point-to-point and virtual links the neighbor structure is freed leaving dangling references to it. Any access to the neighbor list after that is bound to stumble over this dangling pointer causing ospfd to crash. Signed-off-by: Jafar Al-Gharaibeh <jafar@atcorp.com> Tested-by: NetDEF CI System <cisystem@netdef.org> (cherry picked from commit bb01bdd740339b0c07d8ed0786811801b2a79192)
2016-04-21 23:22:33 +02:00
/* Set pseudo neighbor to Null */
oi->nbr_self = NULL;
2002-12-13 21:15:29 +01:00
oi->ls_upd_queue = route_table_init();
oi->t_ls_upd_event = NULL;
oi->t_ls_ack_direct = NULL;
oi->crypt_seqnum = time(NULL);
2002-12-13 21:15:29 +01:00
ospf_opaque_type9_lsa_init(oi);
oi->ospf = ospf;
QOBJ_REG(oi, ospf_interface);
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: ospf interface %s vrf %s id %u created",
__func__, ifp->name, ospf_get_name(ospf),
ospf->vrf_id);
2002-12-13 21:15:29 +01:00
return oi;
}
/* Restore an interface to its pre UP state
Used from ism_interface_down only */
void ospf_if_cleanup(struct ospf_interface *oi)
{
struct route_node *rn;
struct listnode *node, *nnode;
2002-12-13 21:15:29 +01:00
struct ospf_neighbor *nbr;
struct ospf_nbr_nbma *nbr_nbma;
struct ospf_lsa *lsa;
/* oi->nbrs and oi->nbr_nbma should be deleted on InterfaceDown event */
2002-12-13 21:15:29 +01:00
/* delete all static neighbors attached to this interface */
for (ALL_LIST_ELEMENTS(oi->nbr_nbma, node, nnode, nbr_nbma)) {
2002-12-13 21:15:29 +01:00
OSPF_POLL_TIMER_OFF(nbr_nbma->t_poll);
2002-12-13 21:15:29 +01:00
if (nbr_nbma->nbr) {
nbr_nbma->nbr->nbr_nbma = NULL;
nbr_nbma->nbr = NULL;
}
2002-12-13 21:15:29 +01:00
nbr_nbma->oi = NULL;
2002-12-13 21:15:29 +01:00
listnode_delete(oi->nbr_nbma, nbr_nbma);
}
/* send Neighbor event KillNbr to all associated neighbors. */
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
if ((nbr = rn->info) != NULL)
if (nbr != oi->nbr_self)
OSPF_NSM_EVENT_EXECUTE(nbr, NSM_KillNbr);
2002-12-13 21:15:29 +01:00
/* Cleanup Link State Acknowlegdment list. */
for (ALL_LIST_ELEMENTS(oi->ls_ack, node, nnode, lsa))
ospf_lsa_unlock(&lsa); /* oi->ls_ack */
2002-12-13 21:15:29 +01:00
list_delete_all_node(oi->ls_ack);
2002-12-13 21:15:29 +01:00
oi->crypt_seqnum = 0;
2002-12-13 21:15:29 +01:00
/* Empty link state update queue */
ospf_ls_upd_queue_empty(oi);
/* Reset pseudo neighbor. */
ospf_nbr_self_reset(oi, oi->ospf->router_id);
2002-12-13 21:15:29 +01:00
}
void ospf_if_free(struct ospf_interface *oi)
{
ospf_if_down(oi);
ospf_fifo_free(oi->obuf);
2002-12-13 21:15:29 +01:00
assert(oi->state == ISM_Down);
2002-12-13 21:15:29 +01:00
ospf_opaque_type9_lsa_term(oi);
QOBJ_UNREG(oi);
2002-12-13 21:15:29 +01:00
/* Free Pseudo Neighbour */
ospf_nbr_delete(oi->nbr_self);
route_table_finish(oi->nbrs);
route_table_finish(oi->ls_upd_queue);
/* Free any lists that should be freed */
list_delete(&oi->nbr_nbma);
2002-12-13 21:15:29 +01:00
list_delete(&oi->ls_ack);
list_delete(&oi->ls_ack_direct.ls_ack);
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: ospf interface %s vrf %s id %u deleted",
__func__, oi->ifp->name, oi->ifp->vrf->name,
oi->ifp->vrf->vrf_id);
2002-12-13 21:15:29 +01:00
ospf_delete_from_if(oi->ifp, oi);
listnode_delete(oi->ospf->oiflist, oi);
2002-12-13 21:15:29 +01:00
listnode_delete(oi->area->oiflist, oi);
thread_cancel_event(master, oi);
2002-12-13 21:15:29 +01:00
memset(oi, 0, sizeof(*oi));
XFREE(MTYPE_OSPF_IF, oi);
}
int ospf_if_is_up(struct ospf_interface *oi)
{
return if_is_up(oi->ifp);
}
struct ospf_interface *ospf_if_exists(struct ospf_interface *oic)
{
struct listnode *node;
struct ospf *ospf;
struct ospf_interface *oi;
if (!oic)
return NULL;
ospf = oic->ospf;
if (ospf == NULL)
return NULL;
for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi))
if (oi == oic)
return oi;
return NULL;
}
/* Lookup OSPF interface by router LSA posistion */
struct ospf_interface *ospf_if_lookup_by_lsa_pos(struct ospf_area *area,
int lsa_pos)
{
struct listnode *node;
struct ospf_interface *oi;
for (ALL_LIST_ELEMENTS_RO(area->oiflist, node, oi)) {
if (lsa_pos >= oi->lsa_pos_beg && lsa_pos < oi->lsa_pos_end)
return oi;
}
return NULL;
}
struct ospf_interface *ospf_if_lookup_by_local_addr(struct ospf *ospf,
struct interface *ifp,
struct in_addr address)
2002-12-13 21:15:29 +01:00
{
struct listnode *node;
2002-12-13 21:15:29 +01:00
struct ospf_interface *oi;
for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi))
if (oi->type != OSPF_IFTYPE_VIRTUALLINK) {
2002-12-13 21:15:29 +01:00
if (ifp && oi->ifp != ifp)
continue;
2002-12-13 21:15:29 +01:00
if (IPV4_ADDR_SAME(&address, &oi->address->u.prefix4))
return oi;
}
2002-12-13 21:15:29 +01:00
return NULL;
}
struct ospf_interface *ospf_if_lookup_by_prefix(struct ospf *ospf,
struct prefix_ipv4 *p)
2002-12-13 21:15:29 +01:00
{
struct listnode *node;
2002-12-13 21:15:29 +01:00
struct ospf_interface *oi;
2002-12-13 21:15:29 +01:00
/* Check each Interface. */
for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
if (oi->type != OSPF_IFTYPE_VIRTUALLINK) {
[PtP over ethernet] New peer flag allows much more addressing flexibility 2006-12-12 Andrew J. Schorr <ajschorr@alumni.princeton.edu> * if.h: (struct connected) Add new ZEBRA_IFA_PEER flag indicating whether a peer address has been configured. Comment now shows the new interpretation of the destination addr: if ZEBRA_IFA_PEER is set, then it must contain the destination address, otherwise it may contain the broadcast address or be NULL. (CONNECTED_DEST_HOST,CONNECTED_POINTOPOINT_HOST) Remove obsolete macros that were specific to IPv4 and not fully general. (CONNECTED_PEER) New macro to check ZEBRA_IFA_PEER flag. (CONNECTED_PREFIX) New macro giving the prefix to insert into the RIB: if CONNECTED_PEER, then use the destination (peer) address, else use the address field. (CONNECTED_ID) New macro to come up with an identifying address for the struct connected. * if.c: (if_lookup_address, connected_lookup_address) Streamline logic with new CONNECTED_PREFIX macro. * prefix.h: (PREFIX_COPY_IPV4, PREFIX_COPY_IPV6) New macros for better performance than the general prefix_copy function. * zclient.c: (zebra_interface_address_read) For non-null destination addresses, set prefixlen to equal the address prefixlen. This is needed to get the new CONNECTED_PREFIX macro to work properly. * connected.c: (connected_up_ipv4, connected_down_ipv4, connected_up_ipv6, connected_down_ipv6) Simplify logic using the new CONNECTED_PREFIX macro. (connected_add_ipv4) Set prefixlen in destination addresses (required by the CONNECTED_PREFIX macro). Use CONNECTED_PEER macro instead of testing for IFF_POINTOPOINT. Delete invalid warning message. Warn about cases where the ZEBRA_IFA_PEER is set but no destination address has been supplied (and turn off the flag). (connected_add_ipv6) Add new flags argument so callers may set the ZEBRA_IFA_PEER flag. If peer/broadcast address satisfies IN6_IS_ADDR_UNSPECIFIED, then reject it with a warning. Set prefixlen in destination address so CONNECTED_PREFIX will work. * connected.h: (connected_add_ipv6) Add new flags argument so callers may set the ZEBRA_IFA_PEER flag. * interface.c: (connected_dump_vty) Use CONNECTED_PEER macro to decide whether the destination address is a peer or broadcast address (instead of checking IFF_BROADCAST and IFF_POINTOPOINT). * if_ioctl.c: (if_getaddrs) Instead of setting a peer address only when the IFF_POINTOPOINT is set, we now accept a peer address whenever it is available and not the same as the local address. Otherwise (no peer address assigned), we check for a broadcast address (regardless of the IFF_BROADCAST flag). And must now pass a flags value of ZEBRA_IFA_PEER to connected_add_ipv4 when a peer address is assigned. The same new logic is used with the IPv6 code as well (and we pass the new flags argument to connected_add_ipv6). (if_get_addr) Do not bother to check IFF_POINTOPOINT: just issue the SIOCGIFDSTADDR ioctl and see if we get back a peer address not matching the local address (and set the ZEBRA_IFA_PEER in that case). If there's no peer address, try to grab SIOCGIFBRDADDR regardless of whether IFF_BROADCAST is set. * if_ioctl_solaris.c: (if_get_addr) Just try the SIOCGLIFDSTADDR ioctl without bothering to check the IFF_POINTOPOINT flag. And if no peer address was found, just try the SIOCGLIFBRDADDR ioctl without checking the IFF_BROADCAST flag. Call connected_add_ipv4 and connected_add_ipv6 with appropriate flags. * if_proc.c: (ifaddr_proc_ipv6) Must pass new flags argument to connected_add_ipv6. * kernel_socket.c: (ifam_read) Must pass new flags argument to connected_add_ipv6. * rt_netlink.c: (netlink_interface_addr) Copy logic from iproute2 to determine local and possible peer address (so there's no longer a test for IFF_POINTOPOINT). Set ZEBRA_IFA_PEER flag appropriately. Pass new flags argument to connected_add_ipv6. (netlink_address) Test !CONNECTED_PEER instead of if_is_broadcast to determine whether the connected destination address is a broadcast address. * bgp_nexthop.c: (bgp_connected_add, bgp_connected_delete) Simplify logic by using new CONNECTED_PREFIX macro. * ospf_interface.c: (ospf_if_is_configured, ospf_if_lookup_by_prefix, ospf_if_lookup_recv_if) Simplify logic using new CONNECTED_PREFIX macro. * ospf_lsa.c: (lsa_link_ptop_set) Using the new CONNECTED_PREFIX macro, both options collapse into the same code. * ospf_snmp.c: (ospf_snmp_if_update) Simplify logic using new CONNECTED_ID macro. (ospf_snmp_is_if_have_addr) Simplify logic using new CONNECTED_PREFIX macro. * ospf_vty.c: (show_ip_ospf_interface_sub) Use new CONNECTED_PEER macro instead of testing the IFF_POINTOPOINT flag. * ospfd.c: (ospf_network_match_iface) Use new CONNECTED_PEER macro instead of testing with if_is_pointopoint. And add commented-out code to implement alternative (in my opinion) more elegant behavior that has no special-case treatment for PtP addresses. (ospf_network_run) Use new CONNECTED_ID macro to simplify logic. * rip_interface.c: (rip_interface_multicast_set) Use new CONNECTED_ID macro to simplify logic. (rip_request_interface_send) Fix minor bug: ipv4_broadcast_addr does not give a useful result if prefixlen is 32 (we require a peer address in such cases). * ripd.c: (rip_update_interface) Fix same bug as above.
2006-12-12 20:18:21 +01:00
struct prefix ptmp;
[PtP over ethernet] New peer flag allows much more addressing flexibility 2006-12-12 Andrew J. Schorr <ajschorr@alumni.princeton.edu> * if.h: (struct connected) Add new ZEBRA_IFA_PEER flag indicating whether a peer address has been configured. Comment now shows the new interpretation of the destination addr: if ZEBRA_IFA_PEER is set, then it must contain the destination address, otherwise it may contain the broadcast address or be NULL. (CONNECTED_DEST_HOST,CONNECTED_POINTOPOINT_HOST) Remove obsolete macros that were specific to IPv4 and not fully general. (CONNECTED_PEER) New macro to check ZEBRA_IFA_PEER flag. (CONNECTED_PREFIX) New macro giving the prefix to insert into the RIB: if CONNECTED_PEER, then use the destination (peer) address, else use the address field. (CONNECTED_ID) New macro to come up with an identifying address for the struct connected. * if.c: (if_lookup_address, connected_lookup_address) Streamline logic with new CONNECTED_PREFIX macro. * prefix.h: (PREFIX_COPY_IPV4, PREFIX_COPY_IPV6) New macros for better performance than the general prefix_copy function. * zclient.c: (zebra_interface_address_read) For non-null destination addresses, set prefixlen to equal the address prefixlen. This is needed to get the new CONNECTED_PREFIX macro to work properly. * connected.c: (connected_up_ipv4, connected_down_ipv4, connected_up_ipv6, connected_down_ipv6) Simplify logic using the new CONNECTED_PREFIX macro. (connected_add_ipv4) Set prefixlen in destination addresses (required by the CONNECTED_PREFIX macro). Use CONNECTED_PEER macro instead of testing for IFF_POINTOPOINT. Delete invalid warning message. Warn about cases where the ZEBRA_IFA_PEER is set but no destination address has been supplied (and turn off the flag). (connected_add_ipv6) Add new flags argument so callers may set the ZEBRA_IFA_PEER flag. If peer/broadcast address satisfies IN6_IS_ADDR_UNSPECIFIED, then reject it with a warning. Set prefixlen in destination address so CONNECTED_PREFIX will work. * connected.h: (connected_add_ipv6) Add new flags argument so callers may set the ZEBRA_IFA_PEER flag. * interface.c: (connected_dump_vty) Use CONNECTED_PEER macro to decide whether the destination address is a peer or broadcast address (instead of checking IFF_BROADCAST and IFF_POINTOPOINT). * if_ioctl.c: (if_getaddrs) Instead of setting a peer address only when the IFF_POINTOPOINT is set, we now accept a peer address whenever it is available and not the same as the local address. Otherwise (no peer address assigned), we check for a broadcast address (regardless of the IFF_BROADCAST flag). And must now pass a flags value of ZEBRA_IFA_PEER to connected_add_ipv4 when a peer address is assigned. The same new logic is used with the IPv6 code as well (and we pass the new flags argument to connected_add_ipv6). (if_get_addr) Do not bother to check IFF_POINTOPOINT: just issue the SIOCGIFDSTADDR ioctl and see if we get back a peer address not matching the local address (and set the ZEBRA_IFA_PEER in that case). If there's no peer address, try to grab SIOCGIFBRDADDR regardless of whether IFF_BROADCAST is set. * if_ioctl_solaris.c: (if_get_addr) Just try the SIOCGLIFDSTADDR ioctl without bothering to check the IFF_POINTOPOINT flag. And if no peer address was found, just try the SIOCGLIFBRDADDR ioctl without checking the IFF_BROADCAST flag. Call connected_add_ipv4 and connected_add_ipv6 with appropriate flags. * if_proc.c: (ifaddr_proc_ipv6) Must pass new flags argument to connected_add_ipv6. * kernel_socket.c: (ifam_read) Must pass new flags argument to connected_add_ipv6. * rt_netlink.c: (netlink_interface_addr) Copy logic from iproute2 to determine local and possible peer address (so there's no longer a test for IFF_POINTOPOINT). Set ZEBRA_IFA_PEER flag appropriately. Pass new flags argument to connected_add_ipv6. (netlink_address) Test !CONNECTED_PEER instead of if_is_broadcast to determine whether the connected destination address is a broadcast address. * bgp_nexthop.c: (bgp_connected_add, bgp_connected_delete) Simplify logic by using new CONNECTED_PREFIX macro. * ospf_interface.c: (ospf_if_is_configured, ospf_if_lookup_by_prefix, ospf_if_lookup_recv_if) Simplify logic using new CONNECTED_PREFIX macro. * ospf_lsa.c: (lsa_link_ptop_set) Using the new CONNECTED_PREFIX macro, both options collapse into the same code. * ospf_snmp.c: (ospf_snmp_if_update) Simplify logic using new CONNECTED_ID macro. (ospf_snmp_is_if_have_addr) Simplify logic using new CONNECTED_PREFIX macro. * ospf_vty.c: (show_ip_ospf_interface_sub) Use new CONNECTED_PEER macro instead of testing the IFF_POINTOPOINT flag. * ospfd.c: (ospf_network_match_iface) Use new CONNECTED_PEER macro instead of testing with if_is_pointopoint. And add commented-out code to implement alternative (in my opinion) more elegant behavior that has no special-case treatment for PtP addresses. (ospf_network_run) Use new CONNECTED_ID macro to simplify logic. * rip_interface.c: (rip_interface_multicast_set) Use new CONNECTED_ID macro to simplify logic. (rip_request_interface_send) Fix minor bug: ipv4_broadcast_addr does not give a useful result if prefixlen is 32 (we require a peer address in such cases). * ripd.c: (rip_update_interface) Fix same bug as above.
2006-12-12 20:18:21 +01:00
prefix_copy(&ptmp, CONNECTED_PREFIX(oi->connected));
apply_mask(&ptmp);
if (prefix_same(&ptmp, (struct prefix *)p))
return oi;
}
}
2002-12-13 21:15:29 +01:00
return NULL;
}
/* determine receiving interface by ifp and source address */
struct ospf_interface *ospf_if_lookup_recv_if(struct ospf *ospf,
struct in_addr src,
struct interface *ifp)
2002-12-13 21:15:29 +01:00
{
struct route_node *rn;
2002-12-13 21:15:29 +01:00
struct prefix_ipv4 addr;
struct ospf_interface *oi, *match;
2002-12-13 21:15:29 +01:00
addr.family = AF_INET;
addr.prefix = src;
addr.prefixlen = IPV4_MAX_BITLEN;
2002-12-13 21:15:29 +01:00
match = NULL;
for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
oi = rn->info;
if (!oi) /* oi can be NULL for PtP aliases */
continue;
2002-12-13 21:15:29 +01:00
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
continue;
if (if_is_loopback(oi->ifp))
continue;
2015-05-20 02:58:13 +02:00
if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED))
match = oi;
else if (prefix_match(CONNECTED_PREFIX(oi->connected),
(struct prefix *)&addr)) {
if ((match == NULL) || (match->address->prefixlen
< oi->address->prefixlen))
[PtP over ethernet] New peer flag allows much more addressing flexibility 2006-12-12 Andrew J. Schorr <ajschorr@alumni.princeton.edu> * if.h: (struct connected) Add new ZEBRA_IFA_PEER flag indicating whether a peer address has been configured. Comment now shows the new interpretation of the destination addr: if ZEBRA_IFA_PEER is set, then it must contain the destination address, otherwise it may contain the broadcast address or be NULL. (CONNECTED_DEST_HOST,CONNECTED_POINTOPOINT_HOST) Remove obsolete macros that were specific to IPv4 and not fully general. (CONNECTED_PEER) New macro to check ZEBRA_IFA_PEER flag. (CONNECTED_PREFIX) New macro giving the prefix to insert into the RIB: if CONNECTED_PEER, then use the destination (peer) address, else use the address field. (CONNECTED_ID) New macro to come up with an identifying address for the struct connected. * if.c: (if_lookup_address, connected_lookup_address) Streamline logic with new CONNECTED_PREFIX macro. * prefix.h: (PREFIX_COPY_IPV4, PREFIX_COPY_IPV6) New macros for better performance than the general prefix_copy function. * zclient.c: (zebra_interface_address_read) For non-null destination addresses, set prefixlen to equal the address prefixlen. This is needed to get the new CONNECTED_PREFIX macro to work properly. * connected.c: (connected_up_ipv4, connected_down_ipv4, connected_up_ipv6, connected_down_ipv6) Simplify logic using the new CONNECTED_PREFIX macro. (connected_add_ipv4) Set prefixlen in destination addresses (required by the CONNECTED_PREFIX macro). Use CONNECTED_PEER macro instead of testing for IFF_POINTOPOINT. Delete invalid warning message. Warn about cases where the ZEBRA_IFA_PEER is set but no destination address has been supplied (and turn off the flag). (connected_add_ipv6) Add new flags argument so callers may set the ZEBRA_IFA_PEER flag. If peer/broadcast address satisfies IN6_IS_ADDR_UNSPECIFIED, then reject it with a warning. Set prefixlen in destination address so CONNECTED_PREFIX will work. * connected.h: (connected_add_ipv6) Add new flags argument so callers may set the ZEBRA_IFA_PEER flag. * interface.c: (connected_dump_vty) Use CONNECTED_PEER macro to decide whether the destination address is a peer or broadcast address (instead of checking IFF_BROADCAST and IFF_POINTOPOINT). * if_ioctl.c: (if_getaddrs) Instead of setting a peer address only when the IFF_POINTOPOINT is set, we now accept a peer address whenever it is available and not the same as the local address. Otherwise (no peer address assigned), we check for a broadcast address (regardless of the IFF_BROADCAST flag). And must now pass a flags value of ZEBRA_IFA_PEER to connected_add_ipv4 when a peer address is assigned. The same new logic is used with the IPv6 code as well (and we pass the new flags argument to connected_add_ipv6). (if_get_addr) Do not bother to check IFF_POINTOPOINT: just issue the SIOCGIFDSTADDR ioctl and see if we get back a peer address not matching the local address (and set the ZEBRA_IFA_PEER in that case). If there's no peer address, try to grab SIOCGIFBRDADDR regardless of whether IFF_BROADCAST is set. * if_ioctl_solaris.c: (if_get_addr) Just try the SIOCGLIFDSTADDR ioctl without bothering to check the IFF_POINTOPOINT flag. And if no peer address was found, just try the SIOCGLIFBRDADDR ioctl without checking the IFF_BROADCAST flag. Call connected_add_ipv4 and connected_add_ipv6 with appropriate flags. * if_proc.c: (ifaddr_proc_ipv6) Must pass new flags argument to connected_add_ipv6. * kernel_socket.c: (ifam_read) Must pass new flags argument to connected_add_ipv6. * rt_netlink.c: (netlink_interface_addr) Copy logic from iproute2 to determine local and possible peer address (so there's no longer a test for IFF_POINTOPOINT). Set ZEBRA_IFA_PEER flag appropriately. Pass new flags argument to connected_add_ipv6. (netlink_address) Test !CONNECTED_PEER instead of if_is_broadcast to determine whether the connected destination address is a broadcast address. * bgp_nexthop.c: (bgp_connected_add, bgp_connected_delete) Simplify logic by using new CONNECTED_PREFIX macro. * ospf_interface.c: (ospf_if_is_configured, ospf_if_lookup_by_prefix, ospf_if_lookup_recv_if) Simplify logic using new CONNECTED_PREFIX macro. * ospf_lsa.c: (lsa_link_ptop_set) Using the new CONNECTED_PREFIX macro, both options collapse into the same code. * ospf_snmp.c: (ospf_snmp_if_update) Simplify logic using new CONNECTED_ID macro. (ospf_snmp_is_if_have_addr) Simplify logic using new CONNECTED_PREFIX macro. * ospf_vty.c: (show_ip_ospf_interface_sub) Use new CONNECTED_PEER macro instead of testing the IFF_POINTOPOINT flag. * ospfd.c: (ospf_network_match_iface) Use new CONNECTED_PEER macro instead of testing with if_is_pointopoint. And add commented-out code to implement alternative (in my opinion) more elegant behavior that has no special-case treatment for PtP addresses. (ospf_network_run) Use new CONNECTED_ID macro to simplify logic. * rip_interface.c: (rip_interface_multicast_set) Use new CONNECTED_ID macro to simplify logic. (rip_request_interface_send) Fix minor bug: ipv4_broadcast_addr does not give a useful result if prefixlen is 32 (we require a peer address in such cases). * ripd.c: (rip_update_interface) Fix same bug as above.
2006-12-12 20:18:21 +01:00
match = oi;
}
2002-12-13 21:15:29 +01:00
}
return match;
}
static void ospf_if_reset_stats(struct ospf_interface *oi)
{
oi->hello_in = oi->hello_out = 0;
oi->db_desc_in = oi->db_desc_out = 0;
oi->ls_req_in = oi->ls_req_out = 0;
oi->ls_upd_in = oi->ls_upd_out = 0;
oi->ls_ack_in = oi->ls_ack_out = 0;
}
2002-12-13 21:15:29 +01:00
void ospf_if_stream_unset(struct ospf_interface *oi)
{
struct ospf *ospf = oi->ospf;
/* flush the interface packet queue */
ospf_fifo_flush(oi->obuf);
/*reset protocol stats */
ospf_if_reset_stats(oi);
if (oi->on_write_q) {
listnode_delete(ospf->oi_write_q, oi);
if (list_isempty(ospf->oi_write_q))
OSPF_TIMER_OFF(ospf->t_write);
oi->on_write_q = 0;
2002-12-13 21:15:29 +01:00
}
}
static struct ospf_if_params *ospf_new_if_params(void)
2002-12-13 21:15:29 +01:00
{
struct ospf_if_params *oip;
oip = XCALLOC(MTYPE_OSPF_IF_PARAMS, sizeof(struct ospf_if_params));
2002-12-13 21:15:29 +01:00
UNSET_IF_PARAM(oip, output_cost_cmd);
UNSET_IF_PARAM(oip, transmit_delay);
UNSET_IF_PARAM(oip, retransmit_interval);
UNSET_IF_PARAM(oip, passive_interface);
UNSET_IF_PARAM(oip, v_hello);
2005-10-21 Paul Jakma <paul.jakma@sun.com> * (general) OSPF fast, sub-second hello and 1s dead-interval support. A warning fix. Millisec support for ospf_timer_dump. Change auto-cost ref-bandwidth to add a comment to write out of config, rather than printing annoying messages to vty on startup. * ospf_dump.c: (ospf_timer_dump) Print out milliseconds too. Callers typically specify a length of 9, so most see millisecs unless they specify the additional length. * ospf_interface.h: (struct ospf_interface) new interface param, fast_hello. * ospf_interface.c: (ospf_if_table_lookup) add brackets, gcc warning fix. (ospf_new_if_params) Initialise fast_hello param. (ospf_free_if_params) Check whether fast_hello is configured. (ospf_if_new_hook) set fast_hello to default. * ospf_ism.h: Wrap OSPF_ISM_TIMER_ON inside do {} while (0) to prevent funny side-effects from its if statement when this macro is used conditionally by other macros. (OSPF_ISM_TIMER_MSEC_ON) new macro, set in milliseconds. (OSPF_HELLO_TIMER_ON) new macro to set hello timer according to whether fast_hello is set. * ospf_ism.c: Update all setting of the hello timer to use either OSPF_ISM_TIMER_MSEC_ON or OSPF_HELLO_TIMER_ON. The former is used when hello is to be sent immediately. * ospf_nsm.c: ditto * ospf_packet.c: (ospf_hello) hello-interval is not checked for mismatch if fast_hello is set. (ospf_read) Annoying nit, fix "no ospf_interface" to be debug rather than a warning, as it can be perfectly normal to receive packets when logical subnets are used. (ospf_make_hello) Set hello-interval to 0 if fast-hellos are configured. * ospf_vty.c: (ospf_auto_cost_reference_bandwidth) annoying nit, don't vty_out if this command is given, it gets tired quick. (show_ip_ospf_interface_sub) Print the hello-interval according to whether fast-hello is set or not. Print the extra 5 millisec characters from (ospf_timer_dump) if fast-hello is configured. (ospf_vty_dead_interval_set) new function, common to all forms of dead-interval command, to set dead-interval and fast-hello correctly. If a dead-interval is given, unset fast-hello, else if a hello-multiplier is set, set dead-interval to 1 and fast-hello to given multiplier. (ip_ospf_dead_interval_addr_cmd) use ospf_vty_dead_interval_set(). (ip_ospf_dead_interval_minimal_addr_cmd) ditto. (no_ip_ospf_dead_interval) Unset fast-hello. (no_ip_ospf_hello_interval) Bug-fix, unset of hello-interval should set it to OSPF_HELLO_INTERVAL_DEFAULT, not OSPF_ROUTER_DEAD_INTERVAL_DEFAULT. (config_write_interface) Write out fast-hello. (ospf_config_write) Write a comment about "auto-cost reference-bandwidth" having to be equal on all routers. Hopefully just as noticeable as old practice of writing to vty, but less annoying. (ospf_vty_if_init) install the two new dead-interval commands. * ospfd.h: Add defines for OSPF_ROUTER_DEAD_INTERVAL_MINIMAL and OSPF_FAST_HELLO_DEFAULT.
2005-10-21 02:45:17 +02:00
UNSET_IF_PARAM(oip, fast_hello);
2002-12-13 21:15:29 +01:00
UNSET_IF_PARAM(oip, v_wait);
UNSET_IF_PARAM(oip, priority);
UNSET_IF_PARAM(oip, type);
UNSET_IF_PARAM(oip, auth_simple);
UNSET_IF_PARAM(oip, auth_crypt);
UNSET_IF_PARAM(oip, auth_type);
UNSET_IF_PARAM(oip, if_area);
oip->auth_crypt = list_new();
oip->network_lsa_seqnum = htonl(OSPF_INITIAL_SEQUENCE_NUMBER);
oip->is_v_wait_set = false;
oip->ptp_dmvpn = 0;
2002-12-13 21:15:29 +01:00
return oip;
}
static void ospf_del_if_params(struct interface *ifp,
struct ospf_if_params *oip)
2002-12-13 21:15:29 +01:00
{
list_delete(&oip->auth_crypt);
ospf_interface_disable_bfd(ifp, oip);
ldp_sync_info_free(&(oip->ldp_sync_info));
2002-12-13 21:15:29 +01:00
XFREE(MTYPE_OSPF_IF_PARAMS, oip);
}
void ospf_free_if_params(struct interface *ifp, struct in_addr addr)
{
struct ospf_if_params *oip;
struct prefix_ipv4 p;
struct route_node *rn;
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
2002-12-13 21:15:29 +01:00
p.prefix = addr;
rn = route_node_lookup(IF_OIFS_PARAMS(ifp), (struct prefix *)&p);
if (!rn || !rn->info)
return;
2002-12-13 21:15:29 +01:00
oip = rn->info;
route_unlock_node(rn);
2002-12-13 21:15:29 +01:00
if (!OSPF_IF_PARAM_CONFIGURED(oip, output_cost_cmd)
&& !OSPF_IF_PARAM_CONFIGURED(oip, transmit_delay)
&& !OSPF_IF_PARAM_CONFIGURED(oip, retransmit_interval)
&& !OSPF_IF_PARAM_CONFIGURED(oip, passive_interface)
&& !OSPF_IF_PARAM_CONFIGURED(oip, v_hello)
2005-10-21 Paul Jakma <paul.jakma@sun.com> * (general) OSPF fast, sub-second hello and 1s dead-interval support. A warning fix. Millisec support for ospf_timer_dump. Change auto-cost ref-bandwidth to add a comment to write out of config, rather than printing annoying messages to vty on startup. * ospf_dump.c: (ospf_timer_dump) Print out milliseconds too. Callers typically specify a length of 9, so most see millisecs unless they specify the additional length. * ospf_interface.h: (struct ospf_interface) new interface param, fast_hello. * ospf_interface.c: (ospf_if_table_lookup) add brackets, gcc warning fix. (ospf_new_if_params) Initialise fast_hello param. (ospf_free_if_params) Check whether fast_hello is configured. (ospf_if_new_hook) set fast_hello to default. * ospf_ism.h: Wrap OSPF_ISM_TIMER_ON inside do {} while (0) to prevent funny side-effects from its if statement when this macro is used conditionally by other macros. (OSPF_ISM_TIMER_MSEC_ON) new macro, set in milliseconds. (OSPF_HELLO_TIMER_ON) new macro to set hello timer according to whether fast_hello is set. * ospf_ism.c: Update all setting of the hello timer to use either OSPF_ISM_TIMER_MSEC_ON or OSPF_HELLO_TIMER_ON. The former is used when hello is to be sent immediately. * ospf_nsm.c: ditto * ospf_packet.c: (ospf_hello) hello-interval is not checked for mismatch if fast_hello is set. (ospf_read) Annoying nit, fix "no ospf_interface" to be debug rather than a warning, as it can be perfectly normal to receive packets when logical subnets are used. (ospf_make_hello) Set hello-interval to 0 if fast-hellos are configured. * ospf_vty.c: (ospf_auto_cost_reference_bandwidth) annoying nit, don't vty_out if this command is given, it gets tired quick. (show_ip_ospf_interface_sub) Print the hello-interval according to whether fast-hello is set or not. Print the extra 5 millisec characters from (ospf_timer_dump) if fast-hello is configured. (ospf_vty_dead_interval_set) new function, common to all forms of dead-interval command, to set dead-interval and fast-hello correctly. If a dead-interval is given, unset fast-hello, else if a hello-multiplier is set, set dead-interval to 1 and fast-hello to given multiplier. (ip_ospf_dead_interval_addr_cmd) use ospf_vty_dead_interval_set(). (ip_ospf_dead_interval_minimal_addr_cmd) ditto. (no_ip_ospf_dead_interval) Unset fast-hello. (no_ip_ospf_hello_interval) Bug-fix, unset of hello-interval should set it to OSPF_HELLO_INTERVAL_DEFAULT, not OSPF_ROUTER_DEAD_INTERVAL_DEFAULT. (config_write_interface) Write out fast-hello. (ospf_config_write) Write a comment about "auto-cost reference-bandwidth" having to be equal on all routers. Hopefully just as noticeable as old practice of writing to vty, but less annoying. (ospf_vty_if_init) install the two new dead-interval commands. * ospfd.h: Add defines for OSPF_ROUTER_DEAD_INTERVAL_MINIMAL and OSPF_FAST_HELLO_DEFAULT.
2005-10-21 02:45:17 +02:00
&& !OSPF_IF_PARAM_CONFIGURED(oip, fast_hello)
2002-12-13 21:15:29 +01:00
&& !OSPF_IF_PARAM_CONFIGURED(oip, v_wait)
&& !OSPF_IF_PARAM_CONFIGURED(oip, priority)
&& !OSPF_IF_PARAM_CONFIGURED(oip, type)
&& !OSPF_IF_PARAM_CONFIGURED(oip, auth_simple)
&& !OSPF_IF_PARAM_CONFIGURED(oip, auth_type)
&& !OSPF_IF_PARAM_CONFIGURED(oip, if_area)
&& listcount(oip->auth_crypt) == 0) {
ospf_del_if_params(ifp, oip);
2002-12-13 21:15:29 +01:00
rn->info = NULL;
route_unlock_node(rn);
}
}
struct ospf_if_params *ospf_lookup_if_params(struct interface *ifp,
struct in_addr addr)
{
struct prefix_ipv4 p;
struct route_node *rn;
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
2002-12-13 21:15:29 +01:00
p.prefix = addr;
2002-12-13 21:15:29 +01:00
rn = route_node_lookup(IF_OIFS_PARAMS(ifp), (struct prefix *)&p);
2002-12-13 21:15:29 +01:00
if (rn) {
route_unlock_node(rn);
return rn->info;
}
2002-12-13 21:15:29 +01:00
return NULL;
}
struct ospf_if_params *ospf_get_if_params(struct interface *ifp,
struct in_addr addr)
{
struct prefix_ipv4 p;
struct route_node *rn;
2002-12-13 21:15:29 +01:00
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
2002-12-13 21:15:29 +01:00
p.prefix = addr;
apply_mask_ipv4(&p);
2002-12-13 21:15:29 +01:00
rn = route_node_get(IF_OIFS_PARAMS(ifp), (struct prefix *)&p);
2002-12-13 21:15:29 +01:00
if (rn->info == NULL)
rn->info = ospf_new_if_params();
else
route_unlock_node(rn);
2002-12-13 21:15:29 +01:00
return rn->info;
}
void ospf_if_update_params(struct interface *ifp, struct in_addr addr)
{
struct route_node *rn;
struct ospf_interface *oi;
2002-12-13 21:15:29 +01:00
for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
if ((oi = rn->info) == NULL)
continue;
2002-12-13 21:15:29 +01:00
if (IPV4_ADDR_SAME(&oi->address->u.prefix4, &addr))
oi->params = ospf_lookup_if_params(
ifp, oi->address->u.prefix4);
}
}
int ospf_if_new_hook(struct interface *ifp)
{
int rc = 0;
ifp->info = XCALLOC(MTYPE_OSPF_IF_INFO, sizeof(struct ospf_if_info));
2002-12-13 21:15:29 +01:00
IF_OIFS(ifp) = route_table_init();
IF_OIFS_PARAMS(ifp) = route_table_init();
2002-12-13 21:15:29 +01:00
IF_DEF_PARAMS(ifp) = ospf_new_if_params();
2002-12-13 21:15:29 +01:00
SET_IF_PARAM(IF_DEF_PARAMS(ifp), transmit_delay);
IF_DEF_PARAMS(ifp)->transmit_delay = OSPF_TRANSMIT_DELAY_DEFAULT;
2002-12-13 21:15:29 +01:00
SET_IF_PARAM(IF_DEF_PARAMS(ifp), retransmit_interval);
IF_DEF_PARAMS(ifp)->retransmit_interval =
OSPF_RETRANSMIT_INTERVAL_DEFAULT;
2002-12-13 21:15:29 +01:00
SET_IF_PARAM(IF_DEF_PARAMS(ifp), priority);
IF_DEF_PARAMS(ifp)->priority = OSPF_ROUTER_PRIORITY_DEFAULT;
IF_DEF_PARAMS(ifp)->mtu_ignore = OSPF_MTU_IGNORE_DEFAULT;
2002-12-13 21:15:29 +01:00
SET_IF_PARAM(IF_DEF_PARAMS(ifp), v_hello);
IF_DEF_PARAMS(ifp)->v_hello = OSPF_HELLO_INTERVAL_DEFAULT;
2005-10-21 Paul Jakma <paul.jakma@sun.com> * (general) OSPF fast, sub-second hello and 1s dead-interval support. A warning fix. Millisec support for ospf_timer_dump. Change auto-cost ref-bandwidth to add a comment to write out of config, rather than printing annoying messages to vty on startup. * ospf_dump.c: (ospf_timer_dump) Print out milliseconds too. Callers typically specify a length of 9, so most see millisecs unless they specify the additional length. * ospf_interface.h: (struct ospf_interface) new interface param, fast_hello. * ospf_interface.c: (ospf_if_table_lookup) add brackets, gcc warning fix. (ospf_new_if_params) Initialise fast_hello param. (ospf_free_if_params) Check whether fast_hello is configured. (ospf_if_new_hook) set fast_hello to default. * ospf_ism.h: Wrap OSPF_ISM_TIMER_ON inside do {} while (0) to prevent funny side-effects from its if statement when this macro is used conditionally by other macros. (OSPF_ISM_TIMER_MSEC_ON) new macro, set in milliseconds. (OSPF_HELLO_TIMER_ON) new macro to set hello timer according to whether fast_hello is set. * ospf_ism.c: Update all setting of the hello timer to use either OSPF_ISM_TIMER_MSEC_ON or OSPF_HELLO_TIMER_ON. The former is used when hello is to be sent immediately. * ospf_nsm.c: ditto * ospf_packet.c: (ospf_hello) hello-interval is not checked for mismatch if fast_hello is set. (ospf_read) Annoying nit, fix "no ospf_interface" to be debug rather than a warning, as it can be perfectly normal to receive packets when logical subnets are used. (ospf_make_hello) Set hello-interval to 0 if fast-hellos are configured. * ospf_vty.c: (ospf_auto_cost_reference_bandwidth) annoying nit, don't vty_out if this command is given, it gets tired quick. (show_ip_ospf_interface_sub) Print the hello-interval according to whether fast-hello is set or not. Print the extra 5 millisec characters from (ospf_timer_dump) if fast-hello is configured. (ospf_vty_dead_interval_set) new function, common to all forms of dead-interval command, to set dead-interval and fast-hello correctly. If a dead-interval is given, unset fast-hello, else if a hello-multiplier is set, set dead-interval to 1 and fast-hello to given multiplier. (ip_ospf_dead_interval_addr_cmd) use ospf_vty_dead_interval_set(). (ip_ospf_dead_interval_minimal_addr_cmd) ditto. (no_ip_ospf_dead_interval) Unset fast-hello. (no_ip_ospf_hello_interval) Bug-fix, unset of hello-interval should set it to OSPF_HELLO_INTERVAL_DEFAULT, not OSPF_ROUTER_DEAD_INTERVAL_DEFAULT. (config_write_interface) Write out fast-hello. (ospf_config_write) Write a comment about "auto-cost reference-bandwidth" having to be equal on all routers. Hopefully just as noticeable as old practice of writing to vty, but less annoying. (ospf_vty_if_init) install the two new dead-interval commands. * ospfd.h: Add defines for OSPF_ROUTER_DEAD_INTERVAL_MINIMAL and OSPF_FAST_HELLO_DEFAULT.
2005-10-21 02:45:17 +02:00
SET_IF_PARAM(IF_DEF_PARAMS(ifp), fast_hello);
IF_DEF_PARAMS(ifp)->fast_hello = OSPF_FAST_HELLO_DEFAULT;
2002-12-13 21:15:29 +01:00
SET_IF_PARAM(IF_DEF_PARAMS(ifp), v_wait);
IF_DEF_PARAMS(ifp)->v_wait = OSPF_ROUTER_DEAD_INTERVAL_DEFAULT;
2002-12-13 21:15:29 +01:00
SET_IF_PARAM(IF_DEF_PARAMS(ifp), auth_simple);
memset(IF_DEF_PARAMS(ifp)->auth_simple, 0, OSPF_AUTH_SIMPLE_SIZE);
2002-12-13 21:15:29 +01:00
SET_IF_PARAM(IF_DEF_PARAMS(ifp), auth_type);
IF_DEF_PARAMS(ifp)->auth_type = OSPF_AUTH_NOTSET;
2002-12-13 21:15:29 +01:00
rc = ospf_opaque_new_if(ifp);
return rc;
}
static int ospf_if_delete_hook(struct interface *ifp)
{
int rc = 0;
struct route_node *rn;
2002-12-13 21:15:29 +01:00
rc = ospf_opaque_del_if(ifp);
/*
* This function must be called before `route_table_finish` due to
* BFD integration need to iterate over the interface neighbors to
* remove all registrations.
*/
ospf_del_if_params(ifp, IF_DEF_PARAMS(ifp));
for (rn = route_top(IF_OIFS_PARAMS(ifp)); rn; rn = route_next(rn))
if (rn->info)
ospf_del_if_params(ifp, rn->info);
ospfd: Prevent use after free on shutdown Running ospf_topo_vrf1 leads us to this valgrind issue: ==2386518== Invalid read of size 8 ==2386518== at 0x4971520: route_top (table.c:401) ==2386518== by 0x181F08: ospf_interface_bfd_apply (ospf_bfd.c:126) ==2386518== by 0x182069: ospf_interface_disable_bfd (ospf_bfd.c:158) ==2386518== by 0x18BF51: ospf_del_if_params (ospf_interface.c:557) ==2386518== by 0x18C584: ospf_if_delete_hook (ospf_interface.c:712) ==2386518== by 0x490CA0B: hook_call_if_del (if.c:61) ==2386518== by 0x490D1F3: if_delete_retain (if.c:286) ==2386518== by 0x490D337: if_delete (if.c:309) ==2386518== by 0x490CDED: if_destroy_via_zapi (if.c:200) ==2386518== by 0x49940A9: zclient_interface_delete (zclient.c:2237) ==2386518== by 0x4998062: zclient_read (zclient.c:3969) ==2386518== by 0x4979529: thread_call (thread.c:1908) ==2386518== by 0x4919918: frr_run (libfrr.c:1164) ==2386518== by 0x181AC7: main (ospf_main.c:235) ==2386518== Address 0x5df39a0 is 0 bytes inside a block of size 56 free'd ==2386518== at 0x48399AB: free (vg_replace_malloc.c:538) ==2386518== by 0x492A03E: qfree (memory.c:141) ==2386518== by 0x4970C6F: route_table_free (table.c:141) ==2386518== by 0x4970A36: route_table_finish (table.c:61) ==2386518== by 0x18C543: ospf_if_delete_hook (ospf_interface.c:708) ==2386518== by 0x490CA0B: hook_call_if_del (if.c:61) ==2386518== by 0x490D1F3: if_delete_retain (if.c:286) ==2386518== by 0x490D337: if_delete (if.c:309) ==2386518== by 0x490CDED: if_destroy_via_zapi (if.c:200) ==2386518== by 0x49940A9: zclient_interface_delete (zclient.c:2237) ==2386518== by 0x4998062: zclient_read (zclient.c:3969) ==2386518== by 0x4979529: thread_call (thread.c:1908) ==2386518== by 0x4919918: frr_run (libfrr.c:1164) ==2386518== by 0x181AC7: main (ospf_main.c:235) ==2386518== Block was alloc'd at ==2386518== at 0x483AB65: calloc (vg_replace_malloc.c:760) ==2386518== by 0x4929EFC: qcalloc (memory.c:116) ==2386518== by 0x49709F8: route_table_init_with_delegate (table.c:53) ==2386518== by 0x49717F4: route_table_init (table.c:528) ==2386518== by 0x18C328: ospf_if_new_hook (ospf_interface.c:659) ==2386518== by 0x490C97D: hook_call_if_add (if.c:60) ==2386518== by 0x490CE85: if_create_name (if.c:223) ==2386518== by 0x490DF32: if_get_by_name (if.c:622) ==2386518== by 0x4993F73: zclient_interface_add (zclient.c:2186) ==2386518== by 0x4998062: zclient_read (zclient.c:3969) ==2386518== by 0x4979529: thread_call (thread.c:1908) ==2386518== by 0x4919918: frr_run (libfrr.c:1164) ==2386518== by 0x181AC7: main (ospf_main.c:235) ==2386518== Fix the ordering to do the individual node tree cleanup after we delete the data we care about. Signed-off-by: Donald Sharp <sharpd@nvidia.com>
2021-11-11 19:25:35 +01:00
route_table_finish(IF_OIFS(ifp));
2002-12-13 21:15:29 +01:00
route_table_finish(IF_OIFS_PARAMS(ifp));
2002-12-13 21:15:29 +01:00
XFREE(MTYPE_OSPF_IF_INFO, ifp->info);
return rc;
}
int ospf_if_is_enable(struct ospf_interface *oi)
{
if (!(if_is_loopback(oi->ifp)))
2002-12-13 21:15:29 +01:00
if (if_is_up(oi->ifp))
return 1;
return 0;
}
2005-02-08 Andrew J. Schorr <ajschorr@alumni.princeton.edu> * ospf_interface.h: Improve passive_interface comment. Add new multicast_memberships bitmask to struct ospf_interface to track active multicast subscriptions. Declare new function ospf_if_set_multicast. * ospf_interface.c: (ospf_if_set_multicast) New function to configure multicast memberships properly based on the current multicast_memberships status and the current values of the ospf_interface state, type, and passive_interface status. (ospf_if_up) Remove call to ospf_if_add_allspfrouters (this is now handled by ism_change_state's call to ospf_if_set_multicast). (ospf_if_down) Remove call to ospf_if_drop_allspfrouters (now handled by ism_change_state). * ospf_ism.c: (ospf_dr_election) Remove logic to join or leave the DRouters multicast group (now handled by ism_change_state's call to ospf_if_set_multicast). (ism_change_state) Add call to ospf_if_set_multicast to change multicast memberships as necessary to reflect the new interface state. * ospf_packet.c: (ospf_hello) When a Hello packet is received on a passive interface: 1. Increase the severity of the error message from LOG_INFO to LOG_WARNING; 2. Add more information to the error message (packet destination address and interface address); and 3. If the packet was sent to ospf-all-routers, then try to fix the multicast group memberships. (ospf_read) When a packet is received on an interface whose state is ISM_Down, enhance the warning message to show the packet destination address, and try to update/fix the multicast group memberships if the packet was sent to a multicast address. When a packet is received for ospf-designated-routers, but the current interface state is not DR or BDR, then increase the severity level of the error message from LOG_INFO to LOG_WARNING, and try to fix the multicast group memberships. * ospf_vty.c: (ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from active to passive. (no_ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from passive to active. (show_ip_ospf_interface_sub) Show multicast group memberships.
2005-02-08 16:37:30 +01:00
void ospf_if_set_multicast(struct ospf_interface *oi)
{
if ((oi->state > ISM_Loopback) && (oi->type != OSPF_IFTYPE_LOOPBACK)
&& (oi->type != OSPF_IFTYPE_VIRTUALLINK)
&& (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_ACTIVE)) {
2005-02-08 Andrew J. Schorr <ajschorr@alumni.princeton.edu> * ospf_interface.h: Improve passive_interface comment. Add new multicast_memberships bitmask to struct ospf_interface to track active multicast subscriptions. Declare new function ospf_if_set_multicast. * ospf_interface.c: (ospf_if_set_multicast) New function to configure multicast memberships properly based on the current multicast_memberships status and the current values of the ospf_interface state, type, and passive_interface status. (ospf_if_up) Remove call to ospf_if_add_allspfrouters (this is now handled by ism_change_state's call to ospf_if_set_multicast). (ospf_if_down) Remove call to ospf_if_drop_allspfrouters (now handled by ism_change_state). * ospf_ism.c: (ospf_dr_election) Remove logic to join or leave the DRouters multicast group (now handled by ism_change_state's call to ospf_if_set_multicast). (ism_change_state) Add call to ospf_if_set_multicast to change multicast memberships as necessary to reflect the new interface state. * ospf_packet.c: (ospf_hello) When a Hello packet is received on a passive interface: 1. Increase the severity of the error message from LOG_INFO to LOG_WARNING; 2. Add more information to the error message (packet destination address and interface address); and 3. If the packet was sent to ospf-all-routers, then try to fix the multicast group memberships. (ospf_read) When a packet is received on an interface whose state is ISM_Down, enhance the warning message to show the packet destination address, and try to update/fix the multicast group memberships if the packet was sent to a multicast address. When a packet is received for ospf-designated-routers, but the current interface state is not DR or BDR, then increase the severity level of the error message from LOG_INFO to LOG_WARNING, and try to fix the multicast group memberships. * ospf_vty.c: (ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from active to passive. (no_ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from passive to active. (show_ip_ospf_interface_sub) Show multicast group memberships.
2005-02-08 16:37:30 +01:00
/* The interface should belong to the OSPF-all-routers group. */
if (!OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS)
2005-02-08 Andrew J. Schorr <ajschorr@alumni.princeton.edu> * ospf_interface.h: Improve passive_interface comment. Add new multicast_memberships bitmask to struct ospf_interface to track active multicast subscriptions. Declare new function ospf_if_set_multicast. * ospf_interface.c: (ospf_if_set_multicast) New function to configure multicast memberships properly based on the current multicast_memberships status and the current values of the ospf_interface state, type, and passive_interface status. (ospf_if_up) Remove call to ospf_if_add_allspfrouters (this is now handled by ism_change_state's call to ospf_if_set_multicast). (ospf_if_down) Remove call to ospf_if_drop_allspfrouters (now handled by ism_change_state). * ospf_ism.c: (ospf_dr_election) Remove logic to join or leave the DRouters multicast group (now handled by ism_change_state's call to ospf_if_set_multicast). (ism_change_state) Add call to ospf_if_set_multicast to change multicast memberships as necessary to reflect the new interface state. * ospf_packet.c: (ospf_hello) When a Hello packet is received on a passive interface: 1. Increase the severity of the error message from LOG_INFO to LOG_WARNING; 2. Add more information to the error message (packet destination address and interface address); and 3. If the packet was sent to ospf-all-routers, then try to fix the multicast group memberships. (ospf_read) When a packet is received on an interface whose state is ISM_Down, enhance the warning message to show the packet destination address, and try to update/fix the multicast group memberships if the packet was sent to a multicast address. When a packet is received for ospf-designated-routers, but the current interface state is not DR or BDR, then increase the severity level of the error message from LOG_INFO to LOG_WARNING, and try to fix the multicast group memberships. * ospf_vty.c: (ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from active to passive. (no_ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from passive to active. (show_ip_ospf_interface_sub) Show multicast group memberships.
2005-02-08 16:37:30 +01:00
&& (ospf_if_add_allspfrouters(oi->ospf, oi->address,
oi->ifp->ifindex)
>= 0))
/* Set the flag only if the system call to join
* succeeded. */
OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS);
2005-02-08 Andrew J. Schorr <ajschorr@alumni.princeton.edu> * ospf_interface.h: Improve passive_interface comment. Add new multicast_memberships bitmask to struct ospf_interface to track active multicast subscriptions. Declare new function ospf_if_set_multicast. * ospf_interface.c: (ospf_if_set_multicast) New function to configure multicast memberships properly based on the current multicast_memberships status and the current values of the ospf_interface state, type, and passive_interface status. (ospf_if_up) Remove call to ospf_if_add_allspfrouters (this is now handled by ism_change_state's call to ospf_if_set_multicast). (ospf_if_down) Remove call to ospf_if_drop_allspfrouters (now handled by ism_change_state). * ospf_ism.c: (ospf_dr_election) Remove logic to join or leave the DRouters multicast group (now handled by ism_change_state's call to ospf_if_set_multicast). (ism_change_state) Add call to ospf_if_set_multicast to change multicast memberships as necessary to reflect the new interface state. * ospf_packet.c: (ospf_hello) When a Hello packet is received on a passive interface: 1. Increase the severity of the error message from LOG_INFO to LOG_WARNING; 2. Add more information to the error message (packet destination address and interface address); and 3. If the packet was sent to ospf-all-routers, then try to fix the multicast group memberships. (ospf_read) When a packet is received on an interface whose state is ISM_Down, enhance the warning message to show the packet destination address, and try to update/fix the multicast group memberships if the packet was sent to a multicast address. When a packet is received for ospf-designated-routers, but the current interface state is not DR or BDR, then increase the severity level of the error message from LOG_INFO to LOG_WARNING, and try to fix the multicast group memberships. * ospf_vty.c: (ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from active to passive. (no_ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from passive to active. (show_ip_ospf_interface_sub) Show multicast group memberships.
2005-02-08 16:37:30 +01:00
} else {
/* The interface should NOT belong to the OSPF-all-routers
* group. */
if (OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS)) {
/* Only actually drop if this is the last reference */
if (OI_MEMBER_COUNT(oi, MEMBER_ALLROUTERS) == 1)
ospf_if_drop_allspfrouters(oi->ospf,
oi->address,
oi->ifp->ifindex);
2005-02-08 Andrew J. Schorr <ajschorr@alumni.princeton.edu> * ospf_interface.h: Improve passive_interface comment. Add new multicast_memberships bitmask to struct ospf_interface to track active multicast subscriptions. Declare new function ospf_if_set_multicast. * ospf_interface.c: (ospf_if_set_multicast) New function to configure multicast memberships properly based on the current multicast_memberships status and the current values of the ospf_interface state, type, and passive_interface status. (ospf_if_up) Remove call to ospf_if_add_allspfrouters (this is now handled by ism_change_state's call to ospf_if_set_multicast). (ospf_if_down) Remove call to ospf_if_drop_allspfrouters (now handled by ism_change_state). * ospf_ism.c: (ospf_dr_election) Remove logic to join or leave the DRouters multicast group (now handled by ism_change_state's call to ospf_if_set_multicast). (ism_change_state) Add call to ospf_if_set_multicast to change multicast memberships as necessary to reflect the new interface state. * ospf_packet.c: (ospf_hello) When a Hello packet is received on a passive interface: 1. Increase the severity of the error message from LOG_INFO to LOG_WARNING; 2. Add more information to the error message (packet destination address and interface address); and 3. If the packet was sent to ospf-all-routers, then try to fix the multicast group memberships. (ospf_read) When a packet is received on an interface whose state is ISM_Down, enhance the warning message to show the packet destination address, and try to update/fix the multicast group memberships if the packet was sent to a multicast address. When a packet is received for ospf-designated-routers, but the current interface state is not DR or BDR, then increase the severity level of the error message from LOG_INFO to LOG_WARNING, and try to fix the multicast group memberships. * ospf_vty.c: (ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from active to passive. (no_ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from passive to active. (show_ip_ospf_interface_sub) Show multicast group memberships.
2005-02-08 16:37:30 +01:00
/* 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. */
OI_MEMBER_LEFT(oi, MEMBER_ALLROUTERS);
}
2005-02-08 Andrew J. Schorr <ajschorr@alumni.princeton.edu> * ospf_interface.h: Improve passive_interface comment. Add new multicast_memberships bitmask to struct ospf_interface to track active multicast subscriptions. Declare new function ospf_if_set_multicast. * ospf_interface.c: (ospf_if_set_multicast) New function to configure multicast memberships properly based on the current multicast_memberships status and the current values of the ospf_interface state, type, and passive_interface status. (ospf_if_up) Remove call to ospf_if_add_allspfrouters (this is now handled by ism_change_state's call to ospf_if_set_multicast). (ospf_if_down) Remove call to ospf_if_drop_allspfrouters (now handled by ism_change_state). * ospf_ism.c: (ospf_dr_election) Remove logic to join or leave the DRouters multicast group (now handled by ism_change_state's call to ospf_if_set_multicast). (ism_change_state) Add call to ospf_if_set_multicast to change multicast memberships as necessary to reflect the new interface state. * ospf_packet.c: (ospf_hello) When a Hello packet is received on a passive interface: 1. Increase the severity of the error message from LOG_INFO to LOG_WARNING; 2. Add more information to the error message (packet destination address and interface address); and 3. If the packet was sent to ospf-all-routers, then try to fix the multicast group memberships. (ospf_read) When a packet is received on an interface whose state is ISM_Down, enhance the warning message to show the packet destination address, and try to update/fix the multicast group memberships if the packet was sent to a multicast address. When a packet is received for ospf-designated-routers, but the current interface state is not DR or BDR, then increase the severity level of the error message from LOG_INFO to LOG_WARNING, and try to fix the multicast group memberships. * ospf_vty.c: (ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from active to passive. (no_ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from passive to active. (show_ip_ospf_interface_sub) Show multicast group memberships.
2005-02-08 16:37:30 +01:00
}
2005-02-08 Andrew J. Schorr <ajschorr@alumni.princeton.edu> * ospf_interface.h: Improve passive_interface comment. Add new multicast_memberships bitmask to struct ospf_interface to track active multicast subscriptions. Declare new function ospf_if_set_multicast. * ospf_interface.c: (ospf_if_set_multicast) New function to configure multicast memberships properly based on the current multicast_memberships status and the current values of the ospf_interface state, type, and passive_interface status. (ospf_if_up) Remove call to ospf_if_add_allspfrouters (this is now handled by ism_change_state's call to ospf_if_set_multicast). (ospf_if_down) Remove call to ospf_if_drop_allspfrouters (now handled by ism_change_state). * ospf_ism.c: (ospf_dr_election) Remove logic to join or leave the DRouters multicast group (now handled by ism_change_state's call to ospf_if_set_multicast). (ism_change_state) Add call to ospf_if_set_multicast to change multicast memberships as necessary to reflect the new interface state. * ospf_packet.c: (ospf_hello) When a Hello packet is received on a passive interface: 1. Increase the severity of the error message from LOG_INFO to LOG_WARNING; 2. Add more information to the error message (packet destination address and interface address); and 3. If the packet was sent to ospf-all-routers, then try to fix the multicast group memberships. (ospf_read) When a packet is received on an interface whose state is ISM_Down, enhance the warning message to show the packet destination address, and try to update/fix the multicast group memberships if the packet was sent to a multicast address. When a packet is received for ospf-designated-routers, but the current interface state is not DR or BDR, then increase the severity level of the error message from LOG_INFO to LOG_WARNING, and try to fix the multicast group memberships. * ospf_vty.c: (ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from active to passive. (no_ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from passive to active. (show_ip_ospf_interface_sub) Show multicast group memberships.
2005-02-08 16:37:30 +01:00
if (((oi->type == OSPF_IFTYPE_BROADCAST)
|| (oi->type == OSPF_IFTYPE_POINTOPOINT))
&& ((oi->state == ISM_DR) || (oi->state == ISM_Backup))
&& (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_ACTIVE)) {
2005-02-08 Andrew J. Schorr <ajschorr@alumni.princeton.edu> * ospf_interface.h: Improve passive_interface comment. Add new multicast_memberships bitmask to struct ospf_interface to track active multicast subscriptions. Declare new function ospf_if_set_multicast. * ospf_interface.c: (ospf_if_set_multicast) New function to configure multicast memberships properly based on the current multicast_memberships status and the current values of the ospf_interface state, type, and passive_interface status. (ospf_if_up) Remove call to ospf_if_add_allspfrouters (this is now handled by ism_change_state's call to ospf_if_set_multicast). (ospf_if_down) Remove call to ospf_if_drop_allspfrouters (now handled by ism_change_state). * ospf_ism.c: (ospf_dr_election) Remove logic to join or leave the DRouters multicast group (now handled by ism_change_state's call to ospf_if_set_multicast). (ism_change_state) Add call to ospf_if_set_multicast to change multicast memberships as necessary to reflect the new interface state. * ospf_packet.c: (ospf_hello) When a Hello packet is received on a passive interface: 1. Increase the severity of the error message from LOG_INFO to LOG_WARNING; 2. Add more information to the error message (packet destination address and interface address); and 3. If the packet was sent to ospf-all-routers, then try to fix the multicast group memberships. (ospf_read) When a packet is received on an interface whose state is ISM_Down, enhance the warning message to show the packet destination address, and try to update/fix the multicast group memberships if the packet was sent to a multicast address. When a packet is received for ospf-designated-routers, but the current interface state is not DR or BDR, then increase the severity level of the error message from LOG_INFO to LOG_WARNING, and try to fix the multicast group memberships. * ospf_vty.c: (ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from active to passive. (no_ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from passive to active. (show_ip_ospf_interface_sub) Show multicast group memberships.
2005-02-08 16:37:30 +01:00
/* The interface should belong to the OSPF-designated-routers
* group. */
if (!OI_MEMBER_CHECK(oi, MEMBER_DROUTERS)
2005-02-08 Andrew J. Schorr <ajschorr@alumni.princeton.edu> * ospf_interface.h: Improve passive_interface comment. Add new multicast_memberships bitmask to struct ospf_interface to track active multicast subscriptions. Declare new function ospf_if_set_multicast. * ospf_interface.c: (ospf_if_set_multicast) New function to configure multicast memberships properly based on the current multicast_memberships status and the current values of the ospf_interface state, type, and passive_interface status. (ospf_if_up) Remove call to ospf_if_add_allspfrouters (this is now handled by ism_change_state's call to ospf_if_set_multicast). (ospf_if_down) Remove call to ospf_if_drop_allspfrouters (now handled by ism_change_state). * ospf_ism.c: (ospf_dr_election) Remove logic to join or leave the DRouters multicast group (now handled by ism_change_state's call to ospf_if_set_multicast). (ism_change_state) Add call to ospf_if_set_multicast to change multicast memberships as necessary to reflect the new interface state. * ospf_packet.c: (ospf_hello) When a Hello packet is received on a passive interface: 1. Increase the severity of the error message from LOG_INFO to LOG_WARNING; 2. Add more information to the error message (packet destination address and interface address); and 3. If the packet was sent to ospf-all-routers, then try to fix the multicast group memberships. (ospf_read) When a packet is received on an interface whose state is ISM_Down, enhance the warning message to show the packet destination address, and try to update/fix the multicast group memberships if the packet was sent to a multicast address. When a packet is received for ospf-designated-routers, but the current interface state is not DR or BDR, then increase the severity level of the error message from LOG_INFO to LOG_WARNING, and try to fix the multicast group memberships. * ospf_vty.c: (ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from active to passive. (no_ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from passive to active. (show_ip_ospf_interface_sub) Show multicast group memberships.
2005-02-08 16:37:30 +01:00
&& (ospf_if_add_alldrouters(oi->ospf, oi->address,
oi->ifp->ifindex)
>= 0))
/* Set the flag only if the system call to join
* succeeded. */
OI_MEMBER_JOINED(oi, MEMBER_DROUTERS);
2005-02-08 Andrew J. Schorr <ajschorr@alumni.princeton.edu> * ospf_interface.h: Improve passive_interface comment. Add new multicast_memberships bitmask to struct ospf_interface to track active multicast subscriptions. Declare new function ospf_if_set_multicast. * ospf_interface.c: (ospf_if_set_multicast) New function to configure multicast memberships properly based on the current multicast_memberships status and the current values of the ospf_interface state, type, and passive_interface status. (ospf_if_up) Remove call to ospf_if_add_allspfrouters (this is now handled by ism_change_state's call to ospf_if_set_multicast). (ospf_if_down) Remove call to ospf_if_drop_allspfrouters (now handled by ism_change_state). * ospf_ism.c: (ospf_dr_election) Remove logic to join or leave the DRouters multicast group (now handled by ism_change_state's call to ospf_if_set_multicast). (ism_change_state) Add call to ospf_if_set_multicast to change multicast memberships as necessary to reflect the new interface state. * ospf_packet.c: (ospf_hello) When a Hello packet is received on a passive interface: 1. Increase the severity of the error message from LOG_INFO to LOG_WARNING; 2. Add more information to the error message (packet destination address and interface address); and 3. If the packet was sent to ospf-all-routers, then try to fix the multicast group memberships. (ospf_read) When a packet is received on an interface whose state is ISM_Down, enhance the warning message to show the packet destination address, and try to update/fix the multicast group memberships if the packet was sent to a multicast address. When a packet is received for ospf-designated-routers, but the current interface state is not DR or BDR, then increase the severity level of the error message from LOG_INFO to LOG_WARNING, and try to fix the multicast group memberships. * ospf_vty.c: (ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from active to passive. (no_ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from passive to active. (show_ip_ospf_interface_sub) Show multicast group memberships.
2005-02-08 16:37:30 +01:00
} else {
/* The interface should NOT belong to the
* OSPF-designated-routers group */
if (OI_MEMBER_CHECK(oi, MEMBER_DROUTERS)) {
/* drop only if last reference */
if (OI_MEMBER_COUNT(oi, MEMBER_DROUTERS) == 1)
ospf_if_drop_alldrouters(oi->ospf, oi->address,
oi->ifp->ifindex);
2005-02-08 Andrew J. Schorr <ajschorr@alumni.princeton.edu> * ospf_interface.h: Improve passive_interface comment. Add new multicast_memberships bitmask to struct ospf_interface to track active multicast subscriptions. Declare new function ospf_if_set_multicast. * ospf_interface.c: (ospf_if_set_multicast) New function to configure multicast memberships properly based on the current multicast_memberships status and the current values of the ospf_interface state, type, and passive_interface status. (ospf_if_up) Remove call to ospf_if_add_allspfrouters (this is now handled by ism_change_state's call to ospf_if_set_multicast). (ospf_if_down) Remove call to ospf_if_drop_allspfrouters (now handled by ism_change_state). * ospf_ism.c: (ospf_dr_election) Remove logic to join or leave the DRouters multicast group (now handled by ism_change_state's call to ospf_if_set_multicast). (ism_change_state) Add call to ospf_if_set_multicast to change multicast memberships as necessary to reflect the new interface state. * ospf_packet.c: (ospf_hello) When a Hello packet is received on a passive interface: 1. Increase the severity of the error message from LOG_INFO to LOG_WARNING; 2. Add more information to the error message (packet destination address and interface address); and 3. If the packet was sent to ospf-all-routers, then try to fix the multicast group memberships. (ospf_read) When a packet is received on an interface whose state is ISM_Down, enhance the warning message to show the packet destination address, and try to update/fix the multicast group memberships if the packet was sent to a multicast address. When a packet is received for ospf-designated-routers, but the current interface state is not DR or BDR, then increase the severity level of the error message from LOG_INFO to LOG_WARNING, and try to fix the multicast group memberships. * ospf_vty.c: (ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from active to passive. (no_ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from passive to active. (show_ip_ospf_interface_sub) Show multicast group memberships.
2005-02-08 16:37:30 +01:00
/* 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. */
OI_MEMBER_LEFT(oi, MEMBER_DROUTERS);
2005-02-08 Andrew J. Schorr <ajschorr@alumni.princeton.edu> * ospf_interface.h: Improve passive_interface comment. Add new multicast_memberships bitmask to struct ospf_interface to track active multicast subscriptions. Declare new function ospf_if_set_multicast. * ospf_interface.c: (ospf_if_set_multicast) New function to configure multicast memberships properly based on the current multicast_memberships status and the current values of the ospf_interface state, type, and passive_interface status. (ospf_if_up) Remove call to ospf_if_add_allspfrouters (this is now handled by ism_change_state's call to ospf_if_set_multicast). (ospf_if_down) Remove call to ospf_if_drop_allspfrouters (now handled by ism_change_state). * ospf_ism.c: (ospf_dr_election) Remove logic to join or leave the DRouters multicast group (now handled by ism_change_state's call to ospf_if_set_multicast). (ism_change_state) Add call to ospf_if_set_multicast to change multicast memberships as necessary to reflect the new interface state. * ospf_packet.c: (ospf_hello) When a Hello packet is received on a passive interface: 1. Increase the severity of the error message from LOG_INFO to LOG_WARNING; 2. Add more information to the error message (packet destination address and interface address); and 3. If the packet was sent to ospf-all-routers, then try to fix the multicast group memberships. (ospf_read) When a packet is received on an interface whose state is ISM_Down, enhance the warning message to show the packet destination address, and try to update/fix the multicast group memberships if the packet was sent to a multicast address. When a packet is received for ospf-designated-routers, but the current interface state is not DR or BDR, then increase the severity level of the error message from LOG_INFO to LOG_WARNING, and try to fix the multicast group memberships. * ospf_vty.c: (ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from active to passive. (no_ospf_passive_interface) Call ospf_if_set_multicast for any ospf interface that may have changed from passive to active. (show_ip_ospf_interface_sub) Show multicast group memberships.
2005-02-08 16:37:30 +01:00
}
}
}
2002-12-13 21:15:29 +01:00
int ospf_if_up(struct ospf_interface *oi)
{
if (oi == NULL)
return 0;
2002-12-13 21:15:29 +01:00
if (oi->type == OSPF_IFTYPE_LOOPBACK)
OSPF_ISM_EVENT_SCHEDULE(oi, ISM_LoopInd);
else {
OSPF_ISM_EVENT_SCHEDULE(oi, ISM_InterfaceUp);
}
2002-12-13 21:15:29 +01:00
return 1;
}
int ospf_if_down(struct ospf_interface *oi)
{
struct ospf *ospf;
struct route_node *rn;
struct ospf_route *or;
struct listnode *nh;
struct ospf_path *op;
2002-12-13 21:15:29 +01:00
if (oi == NULL)
return 0;
ospf = oi->ospf;
/* Cease the HELPER role for all the neighbours
* of this interface.
*/
if (ospf->is_helper_supported) {
struct route_node *rn = NULL;
if (ospf_interface_neighbor_count(oi)) {
for (rn = route_top(oi->nbrs); rn;
rn = route_next(rn)) {
struct ospf_neighbor *nbr = NULL;
if (!rn->info)
continue;
nbr = rn->info;
if (OSPF_GR_IS_ACTIVE_HELPER(nbr))
ospf_gr_helper_exit(
nbr, OSPF_GR_HELPER_TOPO_CHG);
}
}
}
2002-12-13 21:15:29 +01:00
OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown);
/* delete position in router LSA */
oi->lsa_pos_beg = 0;
oi->lsa_pos_end = 0;
2002-12-13 21:15:29 +01:00
/* Shutdown packet reception and sending */
ospf_if_stream_unset(oi);
if (!ospf->new_table)
return 1;
for (rn = route_top(ospf->new_table); rn; rn = route_next(rn)) {
or = rn->info;
if (!or)
continue;
for (nh = listhead(or->paths); nh;
nh = listnextnode_unchecked(nh)) {
op = listgetdata(nh);
if (op->ifindex == oi->ifp->ifindex) {
or->changed = true;
break;
}
}
}
2002-12-13 21:15:29 +01:00
return 1;
}
2002-12-13 21:15:29 +01:00
/* Virtual Link related functions. */
struct ospf_vl_data *ospf_vl_data_new(struct ospf_area *area,
struct in_addr vl_peer)
{
struct ospf_vl_data *vl_data;
vl_data = XCALLOC(MTYPE_OSPF_VL_DATA, sizeof(struct ospf_vl_data));
2002-12-13 21:15:29 +01:00
vl_data->vl_peer.s_addr = vl_peer.s_addr;
vl_data->vl_area_id = area->area_id;
vl_data->vl_area_id_fmt = area->area_id_fmt;
2002-12-13 21:15:29 +01:00
return vl_data;
}
void ospf_vl_data_free(struct ospf_vl_data *vl_data)
{
XFREE(MTYPE_OSPF_VL_DATA, vl_data);
}
unsigned int vlink_count = 0;
2002-12-13 21:15:29 +01:00
struct ospf_interface *ospf_vl_new(struct ospf *ospf,
struct ospf_vl_data *vl_data)
2002-12-13 21:15:29 +01:00
{
struct ospf_interface *voi;
struct interface *vi;
char ifname[INTERFACE_NAMSIZ];
2002-12-13 21:15:29 +01:00
struct ospf_area *area;
struct in_addr area_id;
struct connected *co;
struct prefix_ipv4 *p;
2002-12-13 21:15:29 +01:00
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("ospf_vl_new()(%s): Start", ospf_get_name(ospf));
2002-12-13 21:15:29 +01:00
if (vlink_count == OSPF_VL_MAX_COUNT) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"ospf_vl_new(): Alarm: cannot create more than OSPF_MAX_VL_COUNT virtual links");
2002-12-13 21:15:29 +01:00
return NULL;
}
2002-12-13 21:15:29 +01:00
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"ospf_vl_new(): creating pseudo zebra interface vrf id %u",
ospf->vrf_id);
snprintf(ifname, sizeof(ifname), "VLINK%u", vlink_count);
vi = if_get_by_name(ifname, ospf->vrf_id, ospf->name);
/*
* if_get_by_name sets ZEBRA_INTERFACE_LINKDETECTION
* virtual links don't need this.
*/
UNSET_FLAG(vi->status, ZEBRA_INTERFACE_LINKDETECTION);
2002-12-13 21:15:29 +01:00
co = connected_new();
co->ifp = vi;
listnode_add(vi->connected, co);
2002-12-13 21:15:29 +01:00
p = prefix_ipv4_new();
p->family = AF_INET;
p->prefix.s_addr = INADDR_ANY;
2002-12-13 21:15:29 +01:00
p->prefixlen = 0;
2002-12-13 21:15:29 +01:00
co->address = (struct prefix *)p;
voi = ospf_if_new(ospf, vi, co->address);
2002-12-13 21:15:29 +01:00
if (voi == NULL) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"ospf_vl_new(): Alarm: OSPF int structure is not created");
2002-12-13 21:15:29 +01:00
return NULL;
}
voi->connected = co;
voi->vl_data = vl_data;
voi->ifp->mtu = OSPF_VL_MTU;
voi->type = OSPF_IFTYPE_VIRTUALLINK;
vlink_count++;
2002-12-13 21:15:29 +01:00
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("ospf_vl_new(): Created name: %s", ifname);
2002-12-13 21:15:29 +01:00
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("ospf_vl_new(): set if->name to %s", vi->name);
area_id.s_addr = INADDR_ANY;
area = ospf_area_get(ospf, area_id);
2002-12-13 21:15:29 +01:00
voi->area = area;
2002-12-13 21:15:29 +01:00
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"ospf_vl_new(): set associated area to the backbone");
ospfd: fix - correct neighbor index on changing/p2p/virtual links ospfd keeps a list of neighbor routers for each configured interface. This list is indexed using the neighbor router id in case of point-to-point and virtual link types, otherwise the list is indexed using the neighbor's source IP (RFC 2328, page 96). The router adds itself as a "pseudo" neighbor on each link, and also keeps a pointer called (nbr_self) to the neighbor structure. This takes place when the interface is first configured. Currently ospfd adds this pseudo neighbor before the link parameters are fully configure, including whether the link type is point-to-point or virtual link. This causes the pseudo neighbor to be always indexed using the source IP address regardless of th link type. For point-to-point and virtual links, this causes the lookup for the pseudo neighbor to always fail because the lookup is done using the router id whereas the neighbor was added using its source IP address. This becomes really problematic if there is a state change that requires a rebuild of nbr_self, changing the router id for example. When resetting nbr_self, the router first tries to remove the pseudo neighbor form its neighbor list on each link by looking it up and resetting any references to it before freeing the neighbor structure. since the lookup fails to retrieve any references in the case of point-to-point and virtual links the neighbor structure is freed leaving dangling references to it. Any access to the neighbor list after that is bound to stumble over this dangling pointer causing ospfd to crash. Signed-off-by: Jafar Al-Gharaibeh <jafar@atcorp.com> Tested-by: NetDEF CI System <cisystem@netdef.org> (cherry picked from commit bb01bdd740339b0c07d8ed0786811801b2a79192)
2016-04-21 23:22:33 +02:00
/* Add pseudo neighbor. */
ospf_nbr_self_reset(voi, voi->ospf->router_id);
2002-12-13 21:15:29 +01:00
ospf_area_add_if(voi->area, voi);
2002-12-13 21:15:29 +01:00
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("ospf_vl_new(): Stop");
2002-12-13 21:15:29 +01:00
return voi;
}
static void ospf_vl_if_delete(struct ospf_vl_data *vl_data)
{
ospfd: Prevent use after free on shutdown Address Sanitizer is reporting this issue: ==26177==ERROR: AddressSanitizer: heap-use-after-free on address 0x6120000238d8 at pc 0x7f88f7c4fa93 bp 0x7fff9a641830 sp 0x7fff9a641820 READ of size 8 at 0x6120000238d8 thread T0 #0 0x7f88f7c4fa92 in if_delete lib/if.c:290 #1 0x42192e in ospf_vl_if_delete ospfd/ospf_interface.c:912 #2 0x42192e in ospf_vl_delete ospfd/ospf_interface.c:990 #3 0x4a6208 in no_ospf_area_vlink ospfd/ospf_vty.c:1227 #4 0x7f88f7c1553d in cmd_execute_command_real lib/command.c:1073 #5 0x7f88f7c19b1e in cmd_execute_command lib/command.c:1132 #6 0x7f88f7c19e8e in cmd_execute lib/command.c:1288 #7 0x7f88f7cd7523 in vty_command lib/vty.c:516 #8 0x7f88f7cd79ff in vty_execute lib/vty.c:1285 #9 0x7f88f7cde4f9 in vtysh_read lib/vty.c:2119 #10 0x7f88f7ccb845 in thread_call lib/thread.c:1549 #11 0x7f88f7c5d6a7 in frr_run lib/libfrr.c:1093 #12 0x412976 in main ospfd/ospf_main.c:221 #13 0x7f88f73b082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) #14 0x413c78 in _start (/usr/local/master/sbin/ospfd+0x413c78) Effectively we are in a shutdown phase and as part of shutdown we delete the ospf interface pointer ( ifp->info ). The interface deletion code was modified in the past year to pass in the address of operator to allow us to NULL out the holding pointer. The catch here is that we free the oi and then delete the interface passing in the address of the oi->ifp pointer, causing a use after free. Fixes: #5555 Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
2019-12-18 15:23:38 +01:00
struct interface *ifp = vl_data->vl_oi->ifp;
struct vrf *vrf = ifp->vrf;
ospfd: Prevent use after free on shutdown Address Sanitizer is reporting this issue: ==26177==ERROR: AddressSanitizer: heap-use-after-free on address 0x6120000238d8 at pc 0x7f88f7c4fa93 bp 0x7fff9a641830 sp 0x7fff9a641820 READ of size 8 at 0x6120000238d8 thread T0 #0 0x7f88f7c4fa92 in if_delete lib/if.c:290 #1 0x42192e in ospf_vl_if_delete ospfd/ospf_interface.c:912 #2 0x42192e in ospf_vl_delete ospfd/ospf_interface.c:990 #3 0x4a6208 in no_ospf_area_vlink ospfd/ospf_vty.c:1227 #4 0x7f88f7c1553d in cmd_execute_command_real lib/command.c:1073 #5 0x7f88f7c19b1e in cmd_execute_command lib/command.c:1132 #6 0x7f88f7c19e8e in cmd_execute lib/command.c:1288 #7 0x7f88f7cd7523 in vty_command lib/vty.c:516 #8 0x7f88f7cd79ff in vty_execute lib/vty.c:1285 #9 0x7f88f7cde4f9 in vtysh_read lib/vty.c:2119 #10 0x7f88f7ccb845 in thread_call lib/thread.c:1549 #11 0x7f88f7c5d6a7 in frr_run lib/libfrr.c:1093 #12 0x412976 in main ospfd/ospf_main.c:221 #13 0x7f88f73b082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) #14 0x413c78 in _start (/usr/local/master/sbin/ospfd+0x413c78) Effectively we are in a shutdown phase and as part of shutdown we delete the ospf interface pointer ( ifp->info ). The interface deletion code was modified in the past year to pass in the address of operator to allow us to NULL out the holding pointer. The catch here is that we free the oi and then delete the interface passing in the address of the oi->ifp pointer, causing a use after free. Fixes: #5555 Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
2019-12-18 15:23:38 +01:00
vl_data->vl_oi->address->u.prefix4.s_addr = INADDR_ANY;
2002-12-13 21:15:29 +01:00
vl_data->vl_oi->address->prefixlen = 0;
ospf_if_free(vl_data->vl_oi);
ospfd: Prevent use after free on shutdown Address Sanitizer is reporting this issue: ==26177==ERROR: AddressSanitizer: heap-use-after-free on address 0x6120000238d8 at pc 0x7f88f7c4fa93 bp 0x7fff9a641830 sp 0x7fff9a641820 READ of size 8 at 0x6120000238d8 thread T0 #0 0x7f88f7c4fa92 in if_delete lib/if.c:290 #1 0x42192e in ospf_vl_if_delete ospfd/ospf_interface.c:912 #2 0x42192e in ospf_vl_delete ospfd/ospf_interface.c:990 #3 0x4a6208 in no_ospf_area_vlink ospfd/ospf_vty.c:1227 #4 0x7f88f7c1553d in cmd_execute_command_real lib/command.c:1073 #5 0x7f88f7c19b1e in cmd_execute_command lib/command.c:1132 #6 0x7f88f7c19e8e in cmd_execute lib/command.c:1288 #7 0x7f88f7cd7523 in vty_command lib/vty.c:516 #8 0x7f88f7cd79ff in vty_execute lib/vty.c:1285 #9 0x7f88f7cde4f9 in vtysh_read lib/vty.c:2119 #10 0x7f88f7ccb845 in thread_call lib/thread.c:1549 #11 0x7f88f7c5d6a7 in frr_run lib/libfrr.c:1093 #12 0x412976 in main ospfd/ospf_main.c:221 #13 0x7f88f73b082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) #14 0x413c78 in _start (/usr/local/master/sbin/ospfd+0x413c78) Effectively we are in a shutdown phase and as part of shutdown we delete the ospf interface pointer ( ifp->info ). The interface deletion code was modified in the past year to pass in the address of operator to allow us to NULL out the holding pointer. The catch here is that we free the oi and then delete the interface passing in the address of the oi->ifp pointer, causing a use after free. Fixes: #5555 Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
2019-12-18 15:23:38 +01:00
if_delete(&ifp);
if (!vrf_is_enabled(vrf))
vrf_delete(vrf);
2002-12-13 21:15:29 +01:00
vlink_count--;
}
/* for a defined area, count the number of configured vl
*/
int ospf_vl_count(struct ospf *ospf, struct ospf_area *area)
{
int count = 0;
struct ospf_vl_data *vl_data;
struct listnode *node;
for (ALL_LIST_ELEMENTS_RO(ospf->vlinks, node, vl_data)) {
if (area
&& !IPV4_ADDR_SAME(&vl_data->vl_area_id, &area->area_id))
continue;
count++;
}
return count;
}
[ospfd] Fix SPF of virtual-links 2006-04-24 Paul Jakma <paul.jakma@sun.com> * (general) More Virtual-link fixes, again with much help in testing / debug from Juergen Kammer. Primarily in SPF. * ospf_spf.h: Add guard. ospf_interface.h will include this header. * ospf_interface.h: Modify ospf_vl_lookup definition to take struct ospf as argument, so as to allow for NULL area argument. (struct ospf_vl_data) Remove out_oi, instead add a struct vertex_nexthop, to use as initial nexthop for backbone paths through a vlink. * ospf_interface.c: (ospf_vl_lookup) Modified to allow NULL area to be passed to indicate "any" (first) area. Add extra debug. (ospf_vl_set_params) vl_oi -> nexthop. Add extra debug. (ospf_vl_up_check) Fix debug, inet_ntoa returns a static buffer.. * ospf_route.c: (ospf_intra_add_router) Vlinks dont go through backbone, don't bother checking. * ospf_spf.c: (static struct list vertex_list) Record vertices that will need to be freed. (cmp) Order network before router vertices, as required, wasn't implemented. (vertex_nexthop_free) Mild additional robustness check. (vertex_parent_free) Take void argument, as this function is passed as list deconstructor for vertex parent list. (ospf_vertex_new) More debug. Set deconstructor for parent list. Track allocated vertices on the vertex_list. (ospf_vertex_free) Get rid of the tricky recursive cleanup of vertices. Now frees only the given vertex. (ospf_vertex_add_parent) Fix assert. (ospf_nexthop_calculation) Fix calculation of nexthop for VLink vertices, lookup the vl_data and use its previously recorded nexthop information. (ospf_spf_calculate) Vertices are freed simply by deleting vertex_list nodes and letting ospf_vertex_free as deconstructor work per-node. (ospf_spf_calculate_timer) Trivial optimisation, leave backbone SPF calculation till last to reduce SPF churn on VLink updates. * ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup (no_ospf_area_vlink_cmd) ditto. (show_ip_ospf_interface_sub) For Vlinks, the peer address is more interesting than the output interface.
2006-05-04 09:32:57 +02:00
/* Look up vl_data for given peer, optionally qualified to be in the
* specified area. NULL area returns first found..
*/
struct ospf_vl_data *ospf_vl_lookup(struct ospf *ospf, struct ospf_area *area,
struct in_addr vl_peer)
2002-12-13 21:15:29 +01:00
{
struct ospf_vl_data *vl_data;
struct listnode *node;
[ospfd] Fix SPF of virtual-links 2006-04-24 Paul Jakma <paul.jakma@sun.com> * (general) More Virtual-link fixes, again with much help in testing / debug from Juergen Kammer. Primarily in SPF. * ospf_spf.h: Add guard. ospf_interface.h will include this header. * ospf_interface.h: Modify ospf_vl_lookup definition to take struct ospf as argument, so as to allow for NULL area argument. (struct ospf_vl_data) Remove out_oi, instead add a struct vertex_nexthop, to use as initial nexthop for backbone paths through a vlink. * ospf_interface.c: (ospf_vl_lookup) Modified to allow NULL area to be passed to indicate "any" (first) area. Add extra debug. (ospf_vl_set_params) vl_oi -> nexthop. Add extra debug. (ospf_vl_up_check) Fix debug, inet_ntoa returns a static buffer.. * ospf_route.c: (ospf_intra_add_router) Vlinks dont go through backbone, don't bother checking. * ospf_spf.c: (static struct list vertex_list) Record vertices that will need to be freed. (cmp) Order network before router vertices, as required, wasn't implemented. (vertex_nexthop_free) Mild additional robustness check. (vertex_parent_free) Take void argument, as this function is passed as list deconstructor for vertex parent list. (ospf_vertex_new) More debug. Set deconstructor for parent list. Track allocated vertices on the vertex_list. (ospf_vertex_free) Get rid of the tricky recursive cleanup of vertices. Now frees only the given vertex. (ospf_vertex_add_parent) Fix assert. (ospf_nexthop_calculation) Fix calculation of nexthop for VLink vertices, lookup the vl_data and use its previously recorded nexthop information. (ospf_spf_calculate) Vertices are freed simply by deleting vertex_list nodes and letting ospf_vertex_free as deconstructor work per-node. (ospf_spf_calculate_timer) Trivial optimisation, leave backbone SPF calculation till last to reduce SPF churn on VLink updates. * ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup (no_ospf_area_vlink_cmd) ditto. (show_ip_ospf_interface_sub) For Vlinks, the peer address is more interesting than the output interface.
2006-05-04 09:32:57 +02:00
if (IS_DEBUG_OSPF_EVENT) {
zlog_debug("%s: Looking for %pI4", __func__, &vl_peer);
[ospfd] Fix SPF of virtual-links 2006-04-24 Paul Jakma <paul.jakma@sun.com> * (general) More Virtual-link fixes, again with much help in testing / debug from Juergen Kammer. Primarily in SPF. * ospf_spf.h: Add guard. ospf_interface.h will include this header. * ospf_interface.h: Modify ospf_vl_lookup definition to take struct ospf as argument, so as to allow for NULL area argument. (struct ospf_vl_data) Remove out_oi, instead add a struct vertex_nexthop, to use as initial nexthop for backbone paths through a vlink. * ospf_interface.c: (ospf_vl_lookup) Modified to allow NULL area to be passed to indicate "any" (first) area. Add extra debug. (ospf_vl_set_params) vl_oi -> nexthop. Add extra debug. (ospf_vl_up_check) Fix debug, inet_ntoa returns a static buffer.. * ospf_route.c: (ospf_intra_add_router) Vlinks dont go through backbone, don't bother checking. * ospf_spf.c: (static struct list vertex_list) Record vertices that will need to be freed. (cmp) Order network before router vertices, as required, wasn't implemented. (vertex_nexthop_free) Mild additional robustness check. (vertex_parent_free) Take void argument, as this function is passed as list deconstructor for vertex parent list. (ospf_vertex_new) More debug. Set deconstructor for parent list. Track allocated vertices on the vertex_list. (ospf_vertex_free) Get rid of the tricky recursive cleanup of vertices. Now frees only the given vertex. (ospf_vertex_add_parent) Fix assert. (ospf_nexthop_calculation) Fix calculation of nexthop for VLink vertices, lookup the vl_data and use its previously recorded nexthop information. (ospf_spf_calculate) Vertices are freed simply by deleting vertex_list nodes and letting ospf_vertex_free as deconstructor work per-node. (ospf_spf_calculate_timer) Trivial optimisation, leave backbone SPF calculation till last to reduce SPF churn on VLink updates. * ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup (no_ospf_area_vlink_cmd) ditto. (show_ip_ospf_interface_sub) For Vlinks, the peer address is more interesting than the output interface.
2006-05-04 09:32:57 +02:00
if (area)
zlog_debug("%s: in area %pI4", __func__,
&area->area_id);
[ospfd] Fix SPF of virtual-links 2006-04-24 Paul Jakma <paul.jakma@sun.com> * (general) More Virtual-link fixes, again with much help in testing / debug from Juergen Kammer. Primarily in SPF. * ospf_spf.h: Add guard. ospf_interface.h will include this header. * ospf_interface.h: Modify ospf_vl_lookup definition to take struct ospf as argument, so as to allow for NULL area argument. (struct ospf_vl_data) Remove out_oi, instead add a struct vertex_nexthop, to use as initial nexthop for backbone paths through a vlink. * ospf_interface.c: (ospf_vl_lookup) Modified to allow NULL area to be passed to indicate "any" (first) area. Add extra debug. (ospf_vl_set_params) vl_oi -> nexthop. Add extra debug. (ospf_vl_up_check) Fix debug, inet_ntoa returns a static buffer.. * ospf_route.c: (ospf_intra_add_router) Vlinks dont go through backbone, don't bother checking. * ospf_spf.c: (static struct list vertex_list) Record vertices that will need to be freed. (cmp) Order network before router vertices, as required, wasn't implemented. (vertex_nexthop_free) Mild additional robustness check. (vertex_parent_free) Take void argument, as this function is passed as list deconstructor for vertex parent list. (ospf_vertex_new) More debug. Set deconstructor for parent list. Track allocated vertices on the vertex_list. (ospf_vertex_free) Get rid of the tricky recursive cleanup of vertices. Now frees only the given vertex. (ospf_vertex_add_parent) Fix assert. (ospf_nexthop_calculation) Fix calculation of nexthop for VLink vertices, lookup the vl_data and use its previously recorded nexthop information. (ospf_spf_calculate) Vertices are freed simply by deleting vertex_list nodes and letting ospf_vertex_free as deconstructor work per-node. (ospf_spf_calculate_timer) Trivial optimisation, leave backbone SPF calculation till last to reduce SPF churn on VLink updates. * ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup (no_ospf_area_vlink_cmd) ditto. (show_ip_ospf_interface_sub) For Vlinks, the peer address is more interesting than the output interface.
2006-05-04 09:32:57 +02:00
}
[ospfd] Fix SPF of virtual-links 2006-04-24 Paul Jakma <paul.jakma@sun.com> * (general) More Virtual-link fixes, again with much help in testing / debug from Juergen Kammer. Primarily in SPF. * ospf_spf.h: Add guard. ospf_interface.h will include this header. * ospf_interface.h: Modify ospf_vl_lookup definition to take struct ospf as argument, so as to allow for NULL area argument. (struct ospf_vl_data) Remove out_oi, instead add a struct vertex_nexthop, to use as initial nexthop for backbone paths through a vlink. * ospf_interface.c: (ospf_vl_lookup) Modified to allow NULL area to be passed to indicate "any" (first) area. Add extra debug. (ospf_vl_set_params) vl_oi -> nexthop. Add extra debug. (ospf_vl_up_check) Fix debug, inet_ntoa returns a static buffer.. * ospf_route.c: (ospf_intra_add_router) Vlinks dont go through backbone, don't bother checking. * ospf_spf.c: (static struct list vertex_list) Record vertices that will need to be freed. (cmp) Order network before router vertices, as required, wasn't implemented. (vertex_nexthop_free) Mild additional robustness check. (vertex_parent_free) Take void argument, as this function is passed as list deconstructor for vertex parent list. (ospf_vertex_new) More debug. Set deconstructor for parent list. Track allocated vertices on the vertex_list. (ospf_vertex_free) Get rid of the tricky recursive cleanup of vertices. Now frees only the given vertex. (ospf_vertex_add_parent) Fix assert. (ospf_nexthop_calculation) Fix calculation of nexthop for VLink vertices, lookup the vl_data and use its previously recorded nexthop information. (ospf_spf_calculate) Vertices are freed simply by deleting vertex_list nodes and letting ospf_vertex_free as deconstructor work per-node. (ospf_spf_calculate_timer) Trivial optimisation, leave backbone SPF calculation till last to reduce SPF churn on VLink updates. * ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup (no_ospf_area_vlink_cmd) ditto. (show_ip_ospf_interface_sub) For Vlinks, the peer address is more interesting than the output interface.
2006-05-04 09:32:57 +02:00
for (ALL_LIST_ELEMENTS_RO(ospf->vlinks, node, vl_data)) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: VL %s, peer %pI4", __func__,
[ospfd] Fix SPF of virtual-links 2006-04-24 Paul Jakma <paul.jakma@sun.com> * (general) More Virtual-link fixes, again with much help in testing / debug from Juergen Kammer. Primarily in SPF. * ospf_spf.h: Add guard. ospf_interface.h will include this header. * ospf_interface.h: Modify ospf_vl_lookup definition to take struct ospf as argument, so as to allow for NULL area argument. (struct ospf_vl_data) Remove out_oi, instead add a struct vertex_nexthop, to use as initial nexthop for backbone paths through a vlink. * ospf_interface.c: (ospf_vl_lookup) Modified to allow NULL area to be passed to indicate "any" (first) area. Add extra debug. (ospf_vl_set_params) vl_oi -> nexthop. Add extra debug. (ospf_vl_up_check) Fix debug, inet_ntoa returns a static buffer.. * ospf_route.c: (ospf_intra_add_router) Vlinks dont go through backbone, don't bother checking. * ospf_spf.c: (static struct list vertex_list) Record vertices that will need to be freed. (cmp) Order network before router vertices, as required, wasn't implemented. (vertex_nexthop_free) Mild additional robustness check. (vertex_parent_free) Take void argument, as this function is passed as list deconstructor for vertex parent list. (ospf_vertex_new) More debug. Set deconstructor for parent list. Track allocated vertices on the vertex_list. (ospf_vertex_free) Get rid of the tricky recursive cleanup of vertices. Now frees only the given vertex. (ospf_vertex_add_parent) Fix assert. (ospf_nexthop_calculation) Fix calculation of nexthop for VLink vertices, lookup the vl_data and use its previously recorded nexthop information. (ospf_spf_calculate) Vertices are freed simply by deleting vertex_list nodes and letting ospf_vertex_free as deconstructor work per-node. (ospf_spf_calculate_timer) Trivial optimisation, leave backbone SPF calculation till last to reduce SPF churn on VLink updates. * ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup (no_ospf_area_vlink_cmd) ditto. (show_ip_ospf_interface_sub) For Vlinks, the peer address is more interesting than the output interface.
2006-05-04 09:32:57 +02:00
vl_data->vl_oi->ifp->name,
&vl_data->vl_peer);
[ospfd] Fix SPF of virtual-links 2006-04-24 Paul Jakma <paul.jakma@sun.com> * (general) More Virtual-link fixes, again with much help in testing / debug from Juergen Kammer. Primarily in SPF. * ospf_spf.h: Add guard. ospf_interface.h will include this header. * ospf_interface.h: Modify ospf_vl_lookup definition to take struct ospf as argument, so as to allow for NULL area argument. (struct ospf_vl_data) Remove out_oi, instead add a struct vertex_nexthop, to use as initial nexthop for backbone paths through a vlink. * ospf_interface.c: (ospf_vl_lookup) Modified to allow NULL area to be passed to indicate "any" (first) area. Add extra debug. (ospf_vl_set_params) vl_oi -> nexthop. Add extra debug. (ospf_vl_up_check) Fix debug, inet_ntoa returns a static buffer.. * ospf_route.c: (ospf_intra_add_router) Vlinks dont go through backbone, don't bother checking. * ospf_spf.c: (static struct list vertex_list) Record vertices that will need to be freed. (cmp) Order network before router vertices, as required, wasn't implemented. (vertex_nexthop_free) Mild additional robustness check. (vertex_parent_free) Take void argument, as this function is passed as list deconstructor for vertex parent list. (ospf_vertex_new) More debug. Set deconstructor for parent list. Track allocated vertices on the vertex_list. (ospf_vertex_free) Get rid of the tricky recursive cleanup of vertices. Now frees only the given vertex. (ospf_vertex_add_parent) Fix assert. (ospf_nexthop_calculation) Fix calculation of nexthop for VLink vertices, lookup the vl_data and use its previously recorded nexthop information. (ospf_spf_calculate) Vertices are freed simply by deleting vertex_list nodes and letting ospf_vertex_free as deconstructor work per-node. (ospf_spf_calculate_timer) Trivial optimisation, leave backbone SPF calculation till last to reduce SPF churn on VLink updates. * ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup (no_ospf_area_vlink_cmd) ditto. (show_ip_ospf_interface_sub) For Vlinks, the peer address is more interesting than the output interface.
2006-05-04 09:32:57 +02:00
if (area
&& !IPV4_ADDR_SAME(&vl_data->vl_area_id, &area->area_id))
continue;
[ospfd] Fix SPF of virtual-links 2006-04-24 Paul Jakma <paul.jakma@sun.com> * (general) More Virtual-link fixes, again with much help in testing / debug from Juergen Kammer. Primarily in SPF. * ospf_spf.h: Add guard. ospf_interface.h will include this header. * ospf_interface.h: Modify ospf_vl_lookup definition to take struct ospf as argument, so as to allow for NULL area argument. (struct ospf_vl_data) Remove out_oi, instead add a struct vertex_nexthop, to use as initial nexthop for backbone paths through a vlink. * ospf_interface.c: (ospf_vl_lookup) Modified to allow NULL area to be passed to indicate "any" (first) area. Add extra debug. (ospf_vl_set_params) vl_oi -> nexthop. Add extra debug. (ospf_vl_up_check) Fix debug, inet_ntoa returns a static buffer.. * ospf_route.c: (ospf_intra_add_router) Vlinks dont go through backbone, don't bother checking. * ospf_spf.c: (static struct list vertex_list) Record vertices that will need to be freed. (cmp) Order network before router vertices, as required, wasn't implemented. (vertex_nexthop_free) Mild additional robustness check. (vertex_parent_free) Take void argument, as this function is passed as list deconstructor for vertex parent list. (ospf_vertex_new) More debug. Set deconstructor for parent list. Track allocated vertices on the vertex_list. (ospf_vertex_free) Get rid of the tricky recursive cleanup of vertices. Now frees only the given vertex. (ospf_vertex_add_parent) Fix assert. (ospf_nexthop_calculation) Fix calculation of nexthop for VLink vertices, lookup the vl_data and use its previously recorded nexthop information. (ospf_spf_calculate) Vertices are freed simply by deleting vertex_list nodes and letting ospf_vertex_free as deconstructor work per-node. (ospf_spf_calculate_timer) Trivial optimisation, leave backbone SPF calculation till last to reduce SPF churn on VLink updates. * ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup (no_ospf_area_vlink_cmd) ditto. (show_ip_ospf_interface_sub) For Vlinks, the peer address is more interesting than the output interface.
2006-05-04 09:32:57 +02:00
if (IPV4_ADDR_SAME(&vl_data->vl_peer, &vl_peer))
return vl_data;
}
2002-12-13 21:15:29 +01:00
return NULL;
}
static void ospf_vl_shutdown(struct ospf_vl_data *vl_data)
{
struct ospf_interface *oi;
if ((oi = vl_data->vl_oi) == NULL)
return;
oi->address->u.prefix4.s_addr = INADDR_ANY;
2002-12-13 21:15:29 +01:00
oi->address->prefixlen = 0;
UNSET_FLAG(oi->ifp->flags, IFF_UP);
/* OSPF_ISM_EVENT_SCHEDULE (oi, ISM_InterfaceDown); */
OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown);
}
void ospf_vl_add(struct ospf *ospf, struct ospf_vl_data *vl_data)
2002-12-13 21:15:29 +01:00
{
listnode_add(ospf->vlinks, vl_data);
hook_call(ospf_vl_add, vl_data);
2002-12-13 21:15:29 +01:00
}
void ospf_vl_delete(struct ospf *ospf, struct ospf_vl_data *vl_data)
2002-12-13 21:15:29 +01:00
{
ospf_vl_shutdown(vl_data);
ospf_vl_if_delete(vl_data);
hook_call(ospf_vl_delete, vl_data);
listnode_delete(ospf->vlinks, vl_data);
2002-12-13 21:15:29 +01:00
ospf_vl_data_free(vl_data);
}
static int ospf_vl_set_params(struct ospf_area *area,
struct ospf_vl_data *vl_data, struct vertex *v)
2002-12-13 21:15:29 +01:00
{
int changed = 0;
struct ospf_interface *voi;
struct listnode *node;
2005-10-18 Paul Jakma <paul.jakma@sun.com> * (general) SPF memory management cleanup and fix for rare double-free bug. * ospf_spf.h: (struct vertex_parent) New struct to hold parent specific data, eg the backlink and the parent vertex pointer, and point to the appropriate general struct vertex_nexthop. (struct vertex_nexthop) remove parent vertex pointer, so this struct can be shared across vertices. (struct vertex) rename list child to list children. Remove list of nexthops, replace with list of vertex_parents. * ospf_spf.c: (update_stat) trivial, remove cast from void *. (vertex_nexthop_new) remove init of parent - field is gone from struct vertex_nexthop. (ospf_canonical_nexthops_free) Remove the canonical vertex_nexthop memory objects. These are the vertex_nexthops attached to the first level of router vertices from the root. (vertex_parent_new) new function, create a vertex_parent. (vertex_parent_free) ditto, but free it. (ospf_vertex_new) Update to match changes to struct vertex. (ospf_vertex_free) Recursively free a struct vertex and its children. The parent list is used as a reference count. vertex_nexthops must be free seperately, if required. (ospf_vertex_dump) update to match struct vertex changes. Print out backlink of parents too. (ospf_vertex_add_parent) ditto. (ospf_lsa_has_link) update comment. (ospf_nexthop_add_unique) removed, not needed anymore. (ospf_nexthop_merge) ditto. (ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent. Simplified to just create vertex_parent and add it. (ospf_spf_flush_parents) new function, flush out the parent list. (ospf_nexthop_calculation) Take the relevant route_lsa_link as an argument, which simplifies things and removes the need for the hack in ospf_nexthop_add_unique - ospf_spf_next already knew exactly which link the cost calculated was for. Update to match struct vertex changes too. (ospf_spf_next) Don't create a vertex for W unnecessarily, if it's there's a vertex already created for W, use it, and hence there's no need to free it either. Update some manipulation/comparisons of distance to match. Flush the parent list if a lower cost path is found. (ospf_spf_route_free) unused, removed. (ospf_spf_dump) match the struct vertex changes, and dump the ifname if possible. (ospf_spf_calculate) At end of SPF, free the canonical nexthops and call ospf_vertex_free on the root vertex to free the entire tree. * ospf_interface.c: (ospf_vl_set_params) match struct vertex changes. * ospf_route.c: (ospf_intra_route_add) ditto (ospf_route_copy_nexthops_from_vertex) ditto * memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
struct vertex_parent *vp = NULL;
unsigned int i;
2002-12-13 21:15:29 +01:00
struct router_lsa *rl;
struct ospf_interface *oi;
2002-12-13 21:15:29 +01:00
voi = vl_data->vl_oi;
2002-12-13 21:15:29 +01:00
if (voi->output_cost != v->distance) {
2002-12-13 21:15:29 +01:00
voi->output_cost = v->distance;
changed = 1;
}
2005-10-18 Paul Jakma <paul.jakma@sun.com> * (general) SPF memory management cleanup and fix for rare double-free bug. * ospf_spf.h: (struct vertex_parent) New struct to hold parent specific data, eg the backlink and the parent vertex pointer, and point to the appropriate general struct vertex_nexthop. (struct vertex_nexthop) remove parent vertex pointer, so this struct can be shared across vertices. (struct vertex) rename list child to list children. Remove list of nexthops, replace with list of vertex_parents. * ospf_spf.c: (update_stat) trivial, remove cast from void *. (vertex_nexthop_new) remove init of parent - field is gone from struct vertex_nexthop. (ospf_canonical_nexthops_free) Remove the canonical vertex_nexthop memory objects. These are the vertex_nexthops attached to the first level of router vertices from the root. (vertex_parent_new) new function, create a vertex_parent. (vertex_parent_free) ditto, but free it. (ospf_vertex_new) Update to match changes to struct vertex. (ospf_vertex_free) Recursively free a struct vertex and its children. The parent list is used as a reference count. vertex_nexthops must be free seperately, if required. (ospf_vertex_dump) update to match struct vertex changes. Print out backlink of parents too. (ospf_vertex_add_parent) ditto. (ospf_lsa_has_link) update comment. (ospf_nexthop_add_unique) removed, not needed anymore. (ospf_nexthop_merge) ditto. (ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent. Simplified to just create vertex_parent and add it. (ospf_spf_flush_parents) new function, flush out the parent list. (ospf_nexthop_calculation) Take the relevant route_lsa_link as an argument, which simplifies things and removes the need for the hack in ospf_nexthop_add_unique - ospf_spf_next already knew exactly which link the cost calculated was for. Update to match struct vertex changes too. (ospf_spf_next) Don't create a vertex for W unnecessarily, if it's there's a vertex already created for W, use it, and hence there's no need to free it either. Update some manipulation/comparisons of distance to match. Flush the parent list if a lower cost path is found. (ospf_spf_route_free) unused, removed. (ospf_spf_dump) match the struct vertex changes, and dump the ifname if possible. (ospf_spf_calculate) At end of SPF, free the canonical nexthops and call ospf_vertex_free on the root vertex to free the entire tree. * ospf_interface.c: (ospf_vl_set_params) match struct vertex changes. * ospf_route.c: (ospf_intra_route_add) ditto (ospf_route_copy_nexthops_from_vertex) ditto * memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
for (ALL_LIST_ELEMENTS_RO(v->parents, node, vp)) {
vl_data->nexthop.lsa_pos = vp->nexthop->lsa_pos;
[ospfd] Fix SPF of virtual-links 2006-04-24 Paul Jakma <paul.jakma@sun.com> * (general) More Virtual-link fixes, again with much help in testing / debug from Juergen Kammer. Primarily in SPF. * ospf_spf.h: Add guard. ospf_interface.h will include this header. * ospf_interface.h: Modify ospf_vl_lookup definition to take struct ospf as argument, so as to allow for NULL area argument. (struct ospf_vl_data) Remove out_oi, instead add a struct vertex_nexthop, to use as initial nexthop for backbone paths through a vlink. * ospf_interface.c: (ospf_vl_lookup) Modified to allow NULL area to be passed to indicate "any" (first) area. Add extra debug. (ospf_vl_set_params) vl_oi -> nexthop. Add extra debug. (ospf_vl_up_check) Fix debug, inet_ntoa returns a static buffer.. * ospf_route.c: (ospf_intra_add_router) Vlinks dont go through backbone, don't bother checking. * ospf_spf.c: (static struct list vertex_list) Record vertices that will need to be freed. (cmp) Order network before router vertices, as required, wasn't implemented. (vertex_nexthop_free) Mild additional robustness check. (vertex_parent_free) Take void argument, as this function is passed as list deconstructor for vertex parent list. (ospf_vertex_new) More debug. Set deconstructor for parent list. Track allocated vertices on the vertex_list. (ospf_vertex_free) Get rid of the tricky recursive cleanup of vertices. Now frees only the given vertex. (ospf_vertex_add_parent) Fix assert. (ospf_nexthop_calculation) Fix calculation of nexthop for VLink vertices, lookup the vl_data and use its previously recorded nexthop information. (ospf_spf_calculate) Vertices are freed simply by deleting vertex_list nodes and letting ospf_vertex_free as deconstructor work per-node. (ospf_spf_calculate_timer) Trivial optimisation, leave backbone SPF calculation till last to reduce SPF churn on VLink updates. * ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup (no_ospf_area_vlink_cmd) ditto. (show_ip_ospf_interface_sub) For Vlinks, the peer address is more interesting than the output interface.
2006-05-04 09:32:57 +02:00
vl_data->nexthop.router = vp->nexthop->router;
/*
* Only deal with interface data when the local
* (calculating) node is the SPF root node
*/
if (!area->spf_dry_run) {
oi = ospf_if_lookup_by_lsa_pos(
area, vl_data->nexthop.lsa_pos);
if (!IPV4_ADDR_SAME(&voi->address->u.prefix4,
&oi->address->u.prefix4))
changed = 1;
voi->address->u.prefix4 = oi->address->u.prefix4;
voi->address->prefixlen = oi->address->prefixlen;
}
break; /* We take the first interface. */
}
2002-12-13 21:15:29 +01:00
rl = (struct router_lsa *)v->lsa;
/* use SPF determined backlink index in struct vertex
* for virtual link destination address
*/
2005-10-18 Paul Jakma <paul.jakma@sun.com> * (general) SPF memory management cleanup and fix for rare double-free bug. * ospf_spf.h: (struct vertex_parent) New struct to hold parent specific data, eg the backlink and the parent vertex pointer, and point to the appropriate general struct vertex_nexthop. (struct vertex_nexthop) remove parent vertex pointer, so this struct can be shared across vertices. (struct vertex) rename list child to list children. Remove list of nexthops, replace with list of vertex_parents. * ospf_spf.c: (update_stat) trivial, remove cast from void *. (vertex_nexthop_new) remove init of parent - field is gone from struct vertex_nexthop. (ospf_canonical_nexthops_free) Remove the canonical vertex_nexthop memory objects. These are the vertex_nexthops attached to the first level of router vertices from the root. (vertex_parent_new) new function, create a vertex_parent. (vertex_parent_free) ditto, but free it. (ospf_vertex_new) Update to match changes to struct vertex. (ospf_vertex_free) Recursively free a struct vertex and its children. The parent list is used as a reference count. vertex_nexthops must be free seperately, if required. (ospf_vertex_dump) update to match struct vertex changes. Print out backlink of parents too. (ospf_vertex_add_parent) ditto. (ospf_lsa_has_link) update comment. (ospf_nexthop_add_unique) removed, not needed anymore. (ospf_nexthop_merge) ditto. (ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent. Simplified to just create vertex_parent and add it. (ospf_spf_flush_parents) new function, flush out the parent list. (ospf_nexthop_calculation) Take the relevant route_lsa_link as an argument, which simplifies things and removes the need for the hack in ospf_nexthop_add_unique - ospf_spf_next already knew exactly which link the cost calculated was for. Update to match struct vertex changes too. (ospf_spf_next) Don't create a vertex for W unnecessarily, if it's there's a vertex already created for W, use it, and hence there's no need to free it either. Update some manipulation/comparisons of distance to match. Flush the parent list if a lower cost path is found. (ospf_spf_route_free) unused, removed. (ospf_spf_dump) match the struct vertex changes, and dump the ifname if possible. (ospf_spf_calculate) At end of SPF, free the canonical nexthops and call ospf_vertex_free on the root vertex to free the entire tree. * ospf_interface.c: (ospf_vl_set_params) match struct vertex changes. * ospf_route.c: (ospf_intra_route_add) ditto (ospf_route_copy_nexthops_from_vertex) ditto * memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
if (vp && vp->backlink >= 0) {
if (!IPV4_ADDR_SAME(&vl_data->peer_addr,
2005-10-18 Paul Jakma <paul.jakma@sun.com> * (general) SPF memory management cleanup and fix for rare double-free bug. * ospf_spf.h: (struct vertex_parent) New struct to hold parent specific data, eg the backlink and the parent vertex pointer, and point to the appropriate general struct vertex_nexthop. (struct vertex_nexthop) remove parent vertex pointer, so this struct can be shared across vertices. (struct vertex) rename list child to list children. Remove list of nexthops, replace with list of vertex_parents. * ospf_spf.c: (update_stat) trivial, remove cast from void *. (vertex_nexthop_new) remove init of parent - field is gone from struct vertex_nexthop. (ospf_canonical_nexthops_free) Remove the canonical vertex_nexthop memory objects. These are the vertex_nexthops attached to the first level of router vertices from the root. (vertex_parent_new) new function, create a vertex_parent. (vertex_parent_free) ditto, but free it. (ospf_vertex_new) Update to match changes to struct vertex. (ospf_vertex_free) Recursively free a struct vertex and its children. The parent list is used as a reference count. vertex_nexthops must be free seperately, if required. (ospf_vertex_dump) update to match struct vertex changes. Print out backlink of parents too. (ospf_vertex_add_parent) ditto. (ospf_lsa_has_link) update comment. (ospf_nexthop_add_unique) removed, not needed anymore. (ospf_nexthop_merge) ditto. (ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent. Simplified to just create vertex_parent and add it. (ospf_spf_flush_parents) new function, flush out the parent list. (ospf_nexthop_calculation) Take the relevant route_lsa_link as an argument, which simplifies things and removes the need for the hack in ospf_nexthop_add_unique - ospf_spf_next already knew exactly which link the cost calculated was for. Update to match struct vertex changes too. (ospf_spf_next) Don't create a vertex for W unnecessarily, if it's there's a vertex already created for W, use it, and hence there's no need to free it either. Update some manipulation/comparisons of distance to match. Flush the parent list if a lower cost path is found. (ospf_spf_route_free) unused, removed. (ospf_spf_dump) match the struct vertex changes, and dump the ifname if possible. (ospf_spf_calculate) At end of SPF, free the canonical nexthops and call ospf_vertex_free on the root vertex to free the entire tree. * ospf_interface.c: (ospf_vl_set_params) match struct vertex changes. * ospf_route.c: (ospf_intra_route_add) ditto (ospf_route_copy_nexthops_from_vertex) ditto * memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
&rl->link[vp->backlink].link_data))
changed = 1;
2005-10-18 Paul Jakma <paul.jakma@sun.com> * (general) SPF memory management cleanup and fix for rare double-free bug. * ospf_spf.h: (struct vertex_parent) New struct to hold parent specific data, eg the backlink and the parent vertex pointer, and point to the appropriate general struct vertex_nexthop. (struct vertex_nexthop) remove parent vertex pointer, so this struct can be shared across vertices. (struct vertex) rename list child to list children. Remove list of nexthops, replace with list of vertex_parents. * ospf_spf.c: (update_stat) trivial, remove cast from void *. (vertex_nexthop_new) remove init of parent - field is gone from struct vertex_nexthop. (ospf_canonical_nexthops_free) Remove the canonical vertex_nexthop memory objects. These are the vertex_nexthops attached to the first level of router vertices from the root. (vertex_parent_new) new function, create a vertex_parent. (vertex_parent_free) ditto, but free it. (ospf_vertex_new) Update to match changes to struct vertex. (ospf_vertex_free) Recursively free a struct vertex and its children. The parent list is used as a reference count. vertex_nexthops must be free seperately, if required. (ospf_vertex_dump) update to match struct vertex changes. Print out backlink of parents too. (ospf_vertex_add_parent) ditto. (ospf_lsa_has_link) update comment. (ospf_nexthop_add_unique) removed, not needed anymore. (ospf_nexthop_merge) ditto. (ospf_spf_consider_nexthop) renamed to ospf_spf_add_parent. Simplified to just create vertex_parent and add it. (ospf_spf_flush_parents) new function, flush out the parent list. (ospf_nexthop_calculation) Take the relevant route_lsa_link as an argument, which simplifies things and removes the need for the hack in ospf_nexthop_add_unique - ospf_spf_next already knew exactly which link the cost calculated was for. Update to match struct vertex changes too. (ospf_spf_next) Don't create a vertex for W unnecessarily, if it's there's a vertex already created for W, use it, and hence there's no need to free it either. Update some manipulation/comparisons of distance to match. Flush the parent list if a lower cost path is found. (ospf_spf_route_free) unused, removed. (ospf_spf_dump) match the struct vertex changes, and dump the ifname if possible. (ospf_spf_calculate) At end of SPF, free the canonical nexthops and call ospf_vertex_free on the root vertex to free the entire tree. * ospf_interface.c: (ospf_vl_set_params) match struct vertex changes. * ospf_route.c: (ospf_intra_route_add) ditto (ospf_route_copy_nexthops_from_vertex) ditto * memtypes.c: (memory_list_ospf) Add MTYPE_OSPF_VERTEX_PARENT.
2005-10-18 06:20:33 +02:00
vl_data->peer_addr = rl->link[vp->backlink].link_data;
} else {
/* This is highly odd, there is no backlink index
* there should be due to the ospf_spf_has_link() check
* in SPF. Lets warn and try pick a link anyway.
*/
zlog_info("ospf_vl_set_params: No backlink for %s!",
vl_data->vl_oi->ifp->name);
for (i = 0; i < ntohs(rl->links); i++) {
switch (rl->link[i].type) {
case LSA_LINK_TYPE_VIRTUALLINK:
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"found back link through VL");
/* fallthru */
case LSA_LINK_TYPE_TRANSIT:
case LSA_LINK_TYPE_POINTOPOINT:
if (!IPV4_ADDR_SAME(&vl_data->peer_addr,
&rl->link[i].link_data))
changed = 1;
vl_data->peer_addr = rl->link[i].link_data;
}
}
2002-12-13 21:15:29 +01:00
}
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("%s: %s peer address: %pI4, cost: %d,%schanged",
__func__, vl_data->vl_oi->ifp->name,
&vl_data->peer_addr, voi->output_cost,
[ospfd] Fix SPF of virtual-links 2006-04-24 Paul Jakma <paul.jakma@sun.com> * (general) More Virtual-link fixes, again with much help in testing / debug from Juergen Kammer. Primarily in SPF. * ospf_spf.h: Add guard. ospf_interface.h will include this header. * ospf_interface.h: Modify ospf_vl_lookup definition to take struct ospf as argument, so as to allow for NULL area argument. (struct ospf_vl_data) Remove out_oi, instead add a struct vertex_nexthop, to use as initial nexthop for backbone paths through a vlink. * ospf_interface.c: (ospf_vl_lookup) Modified to allow NULL area to be passed to indicate "any" (first) area. Add extra debug. (ospf_vl_set_params) vl_oi -> nexthop. Add extra debug. (ospf_vl_up_check) Fix debug, inet_ntoa returns a static buffer.. * ospf_route.c: (ospf_intra_add_router) Vlinks dont go through backbone, don't bother checking. * ospf_spf.c: (static struct list vertex_list) Record vertices that will need to be freed. (cmp) Order network before router vertices, as required, wasn't implemented. (vertex_nexthop_free) Mild additional robustness check. (vertex_parent_free) Take void argument, as this function is passed as list deconstructor for vertex parent list. (ospf_vertex_new) More debug. Set deconstructor for parent list. Track allocated vertices on the vertex_list. (ospf_vertex_free) Get rid of the tricky recursive cleanup of vertices. Now frees only the given vertex. (ospf_vertex_add_parent) Fix assert. (ospf_nexthop_calculation) Fix calculation of nexthop for VLink vertices, lookup the vl_data and use its previously recorded nexthop information. (ospf_spf_calculate) Vertices are freed simply by deleting vertex_list nodes and letting ospf_vertex_free as deconstructor work per-node. (ospf_spf_calculate_timer) Trivial optimisation, leave backbone SPF calculation till last to reduce SPF churn on VLink updates. * ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup (no_ospf_area_vlink_cmd) ditto. (show_ip_ospf_interface_sub) For Vlinks, the peer address is more interesting than the output interface.
2006-05-04 09:32:57 +02:00
(changed ? " " : " un"));
return changed;
2002-12-13 21:15:29 +01:00
}
void ospf_vl_up_check(struct ospf_area *area, struct in_addr rid,
2002-12-13 21:15:29 +01:00
struct vertex *v)
{
struct ospf *ospf = area->ospf;
struct listnode *node;
2002-12-13 21:15:29 +01:00
struct ospf_vl_data *vl_data;
struct ospf_interface *oi;
2002-12-13 21:15:29 +01:00
if (IS_DEBUG_OSPF_EVENT) {
zlog_debug("ospf_vl_up_check(): Start");
zlog_debug("ospf_vl_up_check(): Router ID is %pI4",
&rid);
zlog_debug("ospf_vl_up_check(): Area is %pI4",
&area->area_id);
2002-12-13 21:15:29 +01:00
}
for (ALL_LIST_ELEMENTS_RO(ospf->vlinks, node, vl_data)) {
if (IS_DEBUG_OSPF_EVENT) {
zlog_debug("%s: considering VL, %s in area %pI4",
[ospfd] Fix SPF of virtual-links 2006-04-24 Paul Jakma <paul.jakma@sun.com> * (general) More Virtual-link fixes, again with much help in testing / debug from Juergen Kammer. Primarily in SPF. * ospf_spf.h: Add guard. ospf_interface.h will include this header. * ospf_interface.h: Modify ospf_vl_lookup definition to take struct ospf as argument, so as to allow for NULL area argument. (struct ospf_vl_data) Remove out_oi, instead add a struct vertex_nexthop, to use as initial nexthop for backbone paths through a vlink. * ospf_interface.c: (ospf_vl_lookup) Modified to allow NULL area to be passed to indicate "any" (first) area. Add extra debug. (ospf_vl_set_params) vl_oi -> nexthop. Add extra debug. (ospf_vl_up_check) Fix debug, inet_ntoa returns a static buffer.. * ospf_route.c: (ospf_intra_add_router) Vlinks dont go through backbone, don't bother checking. * ospf_spf.c: (static struct list vertex_list) Record vertices that will need to be freed. (cmp) Order network before router vertices, as required, wasn't implemented. (vertex_nexthop_free) Mild additional robustness check. (vertex_parent_free) Take void argument, as this function is passed as list deconstructor for vertex parent list. (ospf_vertex_new) More debug. Set deconstructor for parent list. Track allocated vertices on the vertex_list. (ospf_vertex_free) Get rid of the tricky recursive cleanup of vertices. Now frees only the given vertex. (ospf_vertex_add_parent) Fix assert. (ospf_nexthop_calculation) Fix calculation of nexthop for VLink vertices, lookup the vl_data and use its previously recorded nexthop information. (ospf_spf_calculate) Vertices are freed simply by deleting vertex_list nodes and letting ospf_vertex_free as deconstructor work per-node. (ospf_spf_calculate_timer) Trivial optimisation, leave backbone SPF calculation till last to reduce SPF churn on VLink updates. * ospf_vty.c: (ospf_find_vl_data) update call to ospf_vl_lookup (no_ospf_area_vlink_cmd) ditto. (show_ip_ospf_interface_sub) For Vlinks, the peer address is more interesting than the output interface.
2006-05-04 09:32:57 +02:00
__func__, vl_data->vl_oi->ifp->name,
&vl_data->vl_area_id);
zlog_debug("%s: peer ID: %pI4", __func__,
&vl_data->vl_peer);
}
2002-12-13 21:15:29 +01:00
if (IPV4_ADDR_SAME(&vl_data->vl_peer, &rid)
&& IPV4_ADDR_SAME(&vl_data->vl_area_id, &area->area_id)) {
oi = vl_data->vl_oi;
SET_FLAG(vl_data->flags, OSPF_VL_FLAG_APPROVED);
2002-12-13 21:15:29 +01:00
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"ospf_vl_up_check(): this VL matched");
2002-12-13 21:15:29 +01:00
if (oi->state == ISM_Down) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
"ospf_vl_up_check(): VL is down, waking it up");
2002-12-13 21:15:29 +01:00
SET_FLAG(oi->ifp->flags, IFF_UP);
OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceUp);
2002-12-13 21:15:29 +01:00
}
if (ospf_vl_set_params(area, vl_data, v)) {
if (IS_DEBUG_OSPF(ism, ISM_EVENTS))
zlog_debug(
"ospf_vl_up_check: VL cost change, scheduling router lsa refresh");
if (ospf->backbone)
ospf_router_lsa_update_area(
ospf->backbone);
else if (IS_DEBUG_OSPF(ism, ISM_EVENTS))
zlog_debug(
"ospf_vl_up_check: VL cost change, no backbone!");
2002-12-13 21:15:29 +01:00
}
}
2002-12-13 21:15:29 +01:00
}
}
void ospf_vl_unapprove(struct ospf *ospf)
2002-12-13 21:15:29 +01:00
{
struct listnode *node;
2002-12-13 21:15:29 +01:00
struct ospf_vl_data *vl_data;
for (ALL_LIST_ELEMENTS_RO(ospf->vlinks, node, vl_data))
UNSET_FLAG(vl_data->flags, OSPF_VL_FLAG_APPROVED);
2002-12-13 21:15:29 +01:00
}
void ospf_vl_shut_unapproved(struct ospf *ospf)
2002-12-13 21:15:29 +01:00
{
struct listnode *node, *nnode;
2002-12-13 21:15:29 +01:00
struct ospf_vl_data *vl_data;
for (ALL_LIST_ELEMENTS(ospf->vlinks, node, nnode, vl_data))
if (!CHECK_FLAG(vl_data->flags, OSPF_VL_FLAG_APPROVED))
ospf_vl_shutdown(vl_data);
2002-12-13 21:15:29 +01:00
}
int ospf_full_virtual_nbrs(struct ospf_area *area)
{
if (IS_DEBUG_OSPF_EVENT) {
zlog_debug(
"counting fully adjacent virtual neighbors in area %pI4",
&area->area_id);
zlog_debug("there are %d of them", area->full_vls);
2002-12-13 21:15:29 +01:00
}
2002-12-13 21:15:29 +01:00
return area->full_vls;
}
int ospf_vls_in_area(struct ospf_area *area)
{
struct listnode *node;
2002-12-13 21:15:29 +01:00
struct ospf_vl_data *vl_data;
int c = 0;
for (ALL_LIST_ELEMENTS_RO(area->ospf->vlinks, node, vl_data))
if (IPV4_ADDR_SAME(&vl_data->vl_area_id, &area->area_id))
c++;
2002-12-13 21:15:29 +01:00
return c;
}
struct crypt_key *ospf_crypt_key_new(void)
2002-12-13 21:15:29 +01:00
{
return XCALLOC(MTYPE_OSPF_CRYPT_KEY, sizeof(struct crypt_key));
2002-12-13 21:15:29 +01:00
}
void ospf_crypt_key_add(struct list *crypt, struct crypt_key *ck)
2002-12-13 21:15:29 +01:00
{
listnode_add(crypt, ck);
}
struct crypt_key *ospf_crypt_key_lookup(struct list *auth_crypt, uint8_t key_id)
2002-12-13 21:15:29 +01:00
{
struct listnode *node;
2002-12-13 21:15:29 +01:00
struct crypt_key *ck;
for (ALL_LIST_ELEMENTS_RO(auth_crypt, node, ck))
if (ck->key_id == key_id)
return ck;
2002-12-13 21:15:29 +01:00
return NULL;
}
int ospf_crypt_key_delete(struct list *auth_crypt, uint8_t key_id)
2002-12-13 21:15:29 +01:00
{
struct listnode *node, *nnode;
2002-12-13 21:15:29 +01:00
struct crypt_key *ck;
for (ALL_LIST_ELEMENTS(auth_crypt, node, nnode, ck)) {
2002-12-13 21:15:29 +01:00
if (ck->key_id == key_id) {
listnode_delete(auth_crypt, ck);
XFREE(MTYPE_OSPF_CRYPT_KEY, ck);
2002-12-13 21:15:29 +01:00
return 1;
}
}
2002-12-13 21:15:29 +01:00
return 0;
}
uint8_t ospf_default_iftype(struct interface *ifp)
{
if (if_is_pointopoint(ifp))
return OSPF_IFTYPE_POINTOPOINT;
else if (if_is_loopback(ifp))
return OSPF_IFTYPE_LOOPBACK;
else
return OSPF_IFTYPE_BROADCAST;
}
void ospf_if_interface(struct interface *ifp)
{
hook_call(ospf_if_update, ifp);
}
uint32_t ospf_if_count_area_params(struct interface *ifp)
{
struct ospf_if_params *params;
struct route_node *rn;
uint32_t count = 0;
params = IF_DEF_PARAMS(ifp);
if (OSPF_IF_PARAM_CONFIGURED(params, if_area))
count++;
for (rn = route_top(IF_OIFS_PARAMS(ifp)); rn; rn = route_next(rn))
if ((params = rn->info)
&& OSPF_IF_PARAM_CONFIGURED(params, if_area))
count++;
return count;
}
static int ospf_ifp_create(struct interface *ifp)
{
struct ospf *ospf = NULL;
ospfd: Set Curr_mtu to when we get the mtu Currently if you start ospfd, bring up neighbors and then issue a tcpdump on a interface ospf is peering over, this causes the neighbor relationship to be restarted: root@spectrum301(mlx-4600c-01):mgmt:~# tcpdump -i vlan402 2020-11-13T21:25:38.059671+00:00 spectrum301 ospfd[29953]: AdjChg: Nbr 202.0.0.3(default) on vlan402:200.0.3.1: Full -> Deleted (KillNbr) 2020-11-13T21:25:38.065520+00:00 spectrum301 ospfd[29953]: ospfTrapNbrStateChange: trap sent: 200.0.3.2 now Deleted/DROther 2020-11-13T21:25:38.065922+00:00 spectrum301 ospfd[29953]: ospfTrapIfStateChange: trap sent: 200.0.3.1 now Down tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on vlan402, link-type EN10MB (Ethernet), capture size 262144 bytes 21:25:38.072330 IP 200.0.3.1 > igmp.mcast.net: igmp v3 report, 1 group record(s) 2020-11-13T21:25:38.080430+00:00 spectrum301 ospfd[29953]: ospfTrapIfStateChange: trap sent: 200.0.3.1 now Point-To-Point 2020-11-13T21:25:38.080654+00:00 spectrum301 ospfd[29953]: SPF Processing Time(usecs): 9734 2020-11-13T21:25:38.080829+00:00 spectrum301 ospfd[29953]: SPF Time: 6422 2020-11-13T21:25:38.080991+00:00 spectrum301 ospfd[29953]: InterArea: 1572 2020-11-13T21:25:38.081152+00:00 spectrum301 ospfd[29953]: Prune: 67 2020-11-13T21:25:38.081329+00:00 spectrum301 ospfd[29953]: RouteInstall: 1396 2020-11-13T21:25:38.081548+00:00 spectrum301 ospfd[29953]: Reason(s) for SPF: N, S, ABR, ASBR 21:25:38.092510 IP 200.0.3.1 > ospf-all.mcast.net: OSPFv2, Hello, length 44 This is happening because the curr_mtu is not being properly stored. It was being set on interface creation( but we have not actually read in the mtu part of the interface data, so it is still 0 ). Modify the code to store the curr_mtu at a point in interface creation *After* we have read in interface data. Ticket: CM-32276 Signed-off-by: Donald Sharp <sharpd@nvidia.com>
2020-12-01 21:37:03 +01:00
struct ospf_if_info *oii;
if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
zlog_debug(
"Zebra: interface add %s vrf %s[%u] index %d flags %llx metric %d mtu %d speed %u",
ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
ifp->ifindex, (unsigned long long)ifp->flags,
ifp->metric, ifp->mtu, ifp->speed);
assert(ifp->info);
ospfd: Set Curr_mtu to when we get the mtu Currently if you start ospfd, bring up neighbors and then issue a tcpdump on a interface ospf is peering over, this causes the neighbor relationship to be restarted: root@spectrum301(mlx-4600c-01):mgmt:~# tcpdump -i vlan402 2020-11-13T21:25:38.059671+00:00 spectrum301 ospfd[29953]: AdjChg: Nbr 202.0.0.3(default) on vlan402:200.0.3.1: Full -> Deleted (KillNbr) 2020-11-13T21:25:38.065520+00:00 spectrum301 ospfd[29953]: ospfTrapNbrStateChange: trap sent: 200.0.3.2 now Deleted/DROther 2020-11-13T21:25:38.065922+00:00 spectrum301 ospfd[29953]: ospfTrapIfStateChange: trap sent: 200.0.3.1 now Down tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on vlan402, link-type EN10MB (Ethernet), capture size 262144 bytes 21:25:38.072330 IP 200.0.3.1 > igmp.mcast.net: igmp v3 report, 1 group record(s) 2020-11-13T21:25:38.080430+00:00 spectrum301 ospfd[29953]: ospfTrapIfStateChange: trap sent: 200.0.3.1 now Point-To-Point 2020-11-13T21:25:38.080654+00:00 spectrum301 ospfd[29953]: SPF Processing Time(usecs): 9734 2020-11-13T21:25:38.080829+00:00 spectrum301 ospfd[29953]: SPF Time: 6422 2020-11-13T21:25:38.080991+00:00 spectrum301 ospfd[29953]: InterArea: 1572 2020-11-13T21:25:38.081152+00:00 spectrum301 ospfd[29953]: Prune: 67 2020-11-13T21:25:38.081329+00:00 spectrum301 ospfd[29953]: RouteInstall: 1396 2020-11-13T21:25:38.081548+00:00 spectrum301 ospfd[29953]: Reason(s) for SPF: N, S, ABR, ASBR 21:25:38.092510 IP 200.0.3.1 > ospf-all.mcast.net: OSPFv2, Hello, length 44 This is happening because the curr_mtu is not being properly stored. It was being set on interface creation( but we have not actually read in the mtu part of the interface data, so it is still 0 ). Modify the code to store the curr_mtu at a point in interface creation *After* we have read in interface data. Ticket: CM-32276 Signed-off-by: Donald Sharp <sharpd@nvidia.com>
2020-12-01 21:37:03 +01:00
oii = ifp->info;
oii->curr_mtu = ifp->mtu;
if (IF_DEF_PARAMS(ifp)
&& !OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS(ifp), type)) {
SET_IF_PARAM(IF_DEF_PARAMS(ifp), type);
IF_DEF_PARAMS(ifp)->type = ospf_default_iftype(ifp);
}
ospf = ifp->vrf->info;
if (!ospf)
return 0;
if (ospf_if_count_area_params(ifp) > 0)
ospf_interface_area_set(ospf, ifp);
ospf_if_recalculate_output_cost(ifp);
ospf_if_update(ospf, ifp);
if (HAS_LINK_PARAMS(ifp))
ospf_mpls_te_update_if(ifp);
hook_call(ospf_if_update, ifp);
return 0;
}
static int ospf_ifp_up(struct interface *ifp)
{
struct ospf_interface *oi;
struct route_node *rn;
struct ospf_if_info *oii = ifp->info;
ospf_if_recalculate_output_cost(ifp);
if (oii && oii->curr_mtu != ifp->mtu) {
if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
zlog_debug(
"Zebra: Interface[%s] MTU change %u -> %u.",
ifp->name, oii->curr_mtu, ifp->mtu);
oii->curr_mtu = ifp->mtu;
/* Must reset the interface (simulate down/up) when MTU
* changes. */
ospf_if_reset(ifp);
return 0;
}
if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
zlog_debug("Zebra: Interface[%s] state change to up.",
ifp->name);
for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
if ((oi = rn->info) == NULL)
continue;
ospf_if_up(oi);
}
if (HAS_LINK_PARAMS(ifp))
ospf_mpls_te_update_if(ifp);
return 0;
}
static int ospf_ifp_down(struct interface *ifp)
{
struct ospf_interface *oi;
struct route_node *node;
if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
zlog_debug("Zebra: Interface[%s] state change to down.",
ifp->name);
for (node = route_top(IF_OIFS(ifp)); node; node = route_next(node)) {
if ((oi = node->info) == NULL)
continue;
ospf_if_down(oi);
}
return 0;
}
static int ospf_ifp_destroy(struct interface *ifp)
{
struct ospf *ospf;
struct route_node *rn;
if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE))
zlog_debug(
"Zebra: interface delete %s vrf %s[%u] index %d flags %llx metric %d mtu %d",
ifp->name, ifp->vrf->name, ifp->vrf->vrf_id,
ifp->ifindex, (unsigned long long)ifp->flags,
ifp->metric, ifp->mtu);
hook_call(ospf_if_delete, ifp);
ospf = ifp->vrf->info;
if (ospf) {
if (ospf_if_count_area_params(ifp) > 0)
ospf_interface_area_unset(ospf, ifp);
}
for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn))
if (rn->info)
ospf_if_free((struct ospf_interface *)rn->info);
return 0;
}
/* Resetting ospf hello timer */
void ospf_reset_hello_timer(struct interface *ifp, struct in_addr addr,
bool is_addr)
{
struct route_node *rn;
if (is_addr) {
struct prefix p;
struct ospf_interface *oi = NULL;
p.u.prefix4 = addr;
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
oi = ospf_if_table_lookup(ifp, &p);
if (oi) {
/* Send hello before restart the hello timer
* to avoid session flaps in case of bigger
* hello interval configurations.
*/
ospf_hello_send(oi);
/* Restart hello timer for this interface */
OSPF_ISM_TIMER_OFF(oi->t_hello);
OSPF_HELLO_TIMER_ON(oi);
}
return;
}
for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
struct ospf_interface *oi = rn->info;
if (!oi)
continue;
/* If hello interval configured on this oi, don't restart. */
if (OSPF_IF_PARAM_CONFIGURED(oi->params, v_hello))
continue;
/* Send hello before restart the hello timer
* to avoid session flaps in case of bigger
* hello interval configurations.
*/
ospf_hello_send(oi);
/* Restart the hello timer. */
OSPF_ISM_TIMER_OFF(oi->t_hello);
OSPF_HELLO_TIMER_ON(oi);
}
}
void ospf_if_init(void)
2002-12-13 21:15:29 +01:00
{
if_zapi_callbacks(ospf_ifp_create, ospf_ifp_up,
ospf_ifp_down, ospf_ifp_destroy);
2002-12-13 21:15:29 +01:00
/* Initialize Zebra interface data structure. */
hook_register_prio(if_add, 0, ospf_if_new_hook);
hook_register_prio(if_del, 0, ospf_if_delete_hook);
2002-12-13 21:15:29 +01:00
}