#include "command.h"
#include "stream.h"
#include "log.h"
+#include "zclient.h"
+#include "bfd.h"
#include "ospfd/ospfd.h"
#include "ospfd/ospf_spf.h"
#include "ospfd/ospf_snmp.h"
#endif /* HAVE_SNMP */
-\f
+
int
ospf_if_get_output_cost (struct ospf_interface *oi)
{
if (oi->output_cost != newcost)
{
oi->output_cost = newcost;
- ospf_router_lsa_timer_add (oi->area);
+ ospf_router_lsa_update_area (oi->area);
}
}
}
}
/* lookup oi for specified prefix/ifp */
-static struct ospf_interface *
+struct ospf_interface *
ospf_if_table_lookup (struct interface *ifp, struct prefix *prefix)
{
struct prefix p;
ospf_add_to_if (ifp, oi);
listnode_add (ospf->oiflist, oi);
- /* Clear self-originated network-LSA. */
- oi->network_lsa_self = NULL;
-
/* Initialize neighbor list. */
oi->nbrs = route_table_init ();
/* Cleanup Link State Acknowlegdment list. */
for (ALL_LIST_ELEMENTS (oi->ls_ack, node, nnode, lsa))
- ospf_lsa_unlock (lsa);
+ ospf_lsa_unlock (&lsa); /* oi->ls_ack */
list_delete_all_node (oi->ls_ack);
oi->crypt_seqnum = 0;
ospf_nbr_delete (oi->nbr_self);
oi->nbr_self = ospf_nbr_new (oi);
ospf_nbr_add_self (oi);
-
- ospf_lsa_unlock (oi->network_lsa_self);
- oi->network_lsa_self = NULL;
- OSPF_TIMER_OFF (oi->t_network_lsa_self);
}
void
listnode_delete (oi->ospf->oiflist, oi);
listnode_delete (oi->area->oiflist, oi);
+ thread_cancel_event (master, oi);
+
memset (oi, 0, sizeof (*oi));
XFREE (MTYPE_OSPF_IF, oi);
}
-\f
+
/*
* check if interface with given address is configured and
* return it if yes. special treatment for PtP networks.
addr.family = AF_INET;
addr.prefix = *address;
addr.prefixlen = IPV4_MAX_PREFIXLEN;
-
+
for (ALL_LIST_ELEMENTS (ospf->oiflist, node, nnode, oi))
if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
{
- if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+ if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED))
+ {
+ if (htonl(oi->ifp->ifindex) == address->s_addr)
+ return oi;
+ }
+ else if (oi->type == OSPF_IFTYPE_POINTOPOINT)
{
- if (CONNECTED_DEST_HOST(oi->connected))
- {
- /* match only destination addr, since local addr is most likely
- * not unique (borrowed from another interface) */
- if (IPV4_ADDR_SAME (address,
- &oi->connected->destination->u.prefix4))
- return oi;
- }
- else
- {
- /* special leniency: match if addr is anywhere on PtP subnet */
- if (prefix_match(oi->address,(struct prefix *)&addr))
- return oi;
- }
+ /* special leniency: match if addr is anywhere on peer subnet */
+ if (prefix_match(CONNECTED_PREFIX(oi->connected),
+ (struct prefix *)&addr))
+ return oi;
}
- else
+ else
{
if (IPV4_ADDR_SAME (address, &oi->address->u.prefix4))
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)
{
struct listnode *node;
struct ospf_interface *oi;
- struct prefix ptmp;
/* Check each Interface. */
for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
{
if (oi->type != OSPF_IFTYPE_VIRTUALLINK)
{
- if ((oi->type == OSPF_IFTYPE_POINTOPOINT) &&
- CONNECTED_DEST_HOST(oi->connected))
- {
- prefix_copy (&ptmp, oi->connected->destination);
- ptmp.prefixlen = IPV4_MAX_BITLEN;
- }
- else
- prefix_copy (&ptmp, oi->address);
-
+ struct prefix ptmp;
+
+ prefix_copy (&ptmp, CONNECTED_PREFIX(oi->connected));
apply_mask (&ptmp);
if (prefix_same (&ptmp, (struct prefix *) p))
return oi;
return NULL;
}
-/* determine receiving interface by source of packet */
+/* determine receiving interface by ifp and source address */
struct ospf_interface *
-ospf_if_lookup_recv_if (struct ospf *ospf, struct in_addr src)
+ospf_if_lookup_recv_if (struct ospf *ospf, struct in_addr src,
+ struct interface *ifp)
{
- struct listnode *node;
+ struct route_node *rn;
struct prefix_ipv4 addr;
struct ospf_interface *oi, *match;
match = NULL;
- for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, node, oi))
+ 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;
+
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
continue;
-
+
if (if_is_loopback (oi->ifp))
continue;
-
- if ((oi->type == OSPF_IFTYPE_POINTOPOINT) &&
- CONNECTED_DEST_HOST(oi->connected))
- {
- if (IPV4_ADDR_SAME (&oi->connected->destination->u.prefix4, &src))
- return oi;
- }
- else
+
+ if (CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED))
+ match = oi;
+ else if (prefix_match (CONNECTED_PREFIX(oi->connected),
+ (struct prefix *) &addr))
{
- if (prefix_match (oi->address, (struct prefix *) &addr))
- {
- if ( (match == NULL) ||
- (match->address->prefixlen < oi->address->prefixlen)
- )
- match = oi;
- }
+ if ( (match == NULL) ||
+ (match->address->prefixlen < oi->address->prefixlen)
+ )
+ match = oi;
}
}
return match;
}
-\f
+
void
ospf_if_stream_set (struct ospf_interface *oi)
{
}
}
-\f
+
static struct ospf_if_params *
ospf_new_if_params (void)
{
struct ospf_if_params *oip;
- oip = XMALLOC (MTYPE_OSPF_IF_PARAMS, sizeof (struct ospf_if_params));
+ oip = XCALLOC (MTYPE_OSPF_IF_PARAMS, sizeof (struct ospf_if_params));
if (!oip)
return NULL;
- memset (oip, 0, sizeof (struct ospf_if_params));
-
UNSET_IF_PARAM (oip, output_cost_cmd);
UNSET_IF_PARAM (oip, transmit_delay);
UNSET_IF_PARAM (oip, retransmit_interval);
oip->auth_crypt = list_new ();
+ oip->network_lsa_seqnum = htonl(OSPF_INITIAL_SEQUENCE_NUMBER);
+
return oip;
}
ospf_del_if_params (struct ospf_if_params *oip)
{
list_delete (oip->auth_crypt);
+ bfd_info_free(&(oip->bfd_info));
XFREE (MTYPE_OSPF_IF_PARAMS, oip);
}
!OSPF_IF_PARAM_CONFIGURED (oip, type) &&
!OSPF_IF_PARAM_CONFIGURED (oip, auth_simple) &&
!OSPF_IF_PARAM_CONFIGURED (oip, auth_type) &&
- listcount (oip->auth_crypt) == 0)
+ listcount (oip->auth_crypt) == 0 &&
+ ntohl (oip->network_lsa_seqnum) != OSPF_INITIAL_SEQUENCE_NUMBER)
{
ospf_del_if_params (oip);
rn->info = NULL;
{
int rc = 0;
- ifp->info = XMALLOC (MTYPE_OSPF_IF_INFO, sizeof (struct ospf_if_info));
- memset (ifp->info, 0, sizeof (struct ospf_if_info));
+ ifp->info = XCALLOC (MTYPE_OSPF_IF_INFO, sizeof (struct ospf_if_info));
IF_OIFS (ifp) = route_table_init ();
IF_OIFS_PARAMS (ifp) = route_table_init ();
IF_DEF_PARAMS (ifp)->mtu_ignore = OSPF_MTU_IGNORE_DEFAULT;
- SET_IF_PARAM (IF_DEF_PARAMS (ifp), passive_interface);
- IF_DEF_PARAMS (ifp)->passive_interface = OSPF_IF_ACTIVE;
-
SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_hello);
IF_DEF_PARAMS (ifp)->v_hello = OSPF_HELLO_INTERVAL_DEFAULT;
if ((oi->state > ISM_Loopback) &&
(oi->type != OSPF_IFTYPE_LOOPBACK) &&
(oi->type != OSPF_IFTYPE_VIRTUALLINK) &&
- (OSPF_IF_PARAM(oi, passive_interface) == OSPF_IF_ACTIVE))
+ (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_ACTIVE))
{
/* The interface should belong to the OSPF-all-routers group. */
- if (!CHECK_FLAG(oi->multicast_memberships, MEMBER_ALLROUTERS) &&
+ if (!OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS) &&
(ospf_if_add_allspfrouters(oi->ospf, oi->address,
oi->ifp->ifindex) >= 0))
- /* Set the flag only if the system call to join succeeded. */
- SET_FLAG(oi->multicast_memberships, MEMBER_ALLROUTERS);
+ /* Set the flag only if the system call to join succeeded. */
+ OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS);
}
else
{
/* The interface should NOT belong to the OSPF-all-routers group. */
- if (CHECK_FLAG(oi->multicast_memberships, MEMBER_ALLROUTERS))
+ if (OI_MEMBER_CHECK(oi, MEMBER_ALLROUTERS))
{
- ospf_if_drop_allspfrouters (oi->ospf, oi->address, oi->ifp->ifindex);
+ /* 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);
/* 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. */
- UNSET_FLAG(oi->multicast_memberships, MEMBER_ALLROUTERS);
+ OI_MEMBER_LEFT(oi,MEMBER_ALLROUTERS);
}
}
if (((oi->type == OSPF_IFTYPE_BROADCAST) ||
(oi->type == OSPF_IFTYPE_POINTOPOINT)) &&
((oi->state == ISM_DR) || (oi->state == ISM_Backup)) &&
- (OSPF_IF_PARAM(oi, passive_interface) == OSPF_IF_ACTIVE))
+ (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_ACTIVE))
{
/* The interface should belong to the OSPF-designated-routers group. */
- if (!CHECK_FLAG(oi->multicast_memberships, MEMBER_DROUTERS) &&
+ if (!OI_MEMBER_CHECK(oi, MEMBER_DROUTERS) &&
(ospf_if_add_alldrouters(oi->ospf, oi->address,
oi->ifp->ifindex) >= 0))
/* Set the flag only if the system call to join succeeded. */
- SET_FLAG(oi->multicast_memberships, MEMBER_DROUTERS);
+ OI_MEMBER_JOINED(oi, MEMBER_DROUTERS);
}
else
{
/* The interface should NOT belong to the OSPF-designated-routers group */
- if (CHECK_FLAG(oi->multicast_memberships, MEMBER_DROUTERS))
+ if (OI_MEMBER_CHECK(oi, MEMBER_DROUTERS))
{
- ospf_if_drop_alldrouters(oi->ospf, oi->address, oi->ifp->ifindex);
+ /* drop only if last reference */
+ if (OI_MEMBER_COUNT(oi, MEMBER_DROUTERS) == 1)
+ ospf_if_drop_alldrouters(oi->ospf, oi->address, oi->ifp->ifindex);
+
/* Unset the flag regardless of whether the system call to leave
the group succeeded, since it's much safer to assume that
we are not a member. */
- UNSET_FLAG(oi->multicast_memberships, MEMBER_DROUTERS);
+ OI_MEMBER_LEFT(oi, MEMBER_DROUTERS);
}
}
}
OSPF_ISM_EVENT_SCHEDULE (oi, ISM_LoopInd);
else
{
+ struct ospf *ospf = ospf_lookup ();
+ if (ospf != NULL)
+ ospf_adjust_sndbuflen (ospf, oi->ifp->mtu);
+ else
+ zlog_warn ("%s: ospf_lookup() returned NULL", __func__);
ospf_if_stream_set (oi);
OSPF_ISM_EVENT_SCHEDULE (oi, ISM_InterfaceUp);
}
return 0;
OSPF_ISM_EVENT_EXECUTE (oi, ISM_InterfaceDown);
+ /* delete position in router LSA */
+ oi->lsa_pos_beg = 0;
+ oi->lsa_pos_end = 0;
/* Shutdown packet reception and sending */
ospf_if_stream_unset (oi);
return 1;
}
-\f
+
/* Virtual Link related functions. */
struct ospf_vl_data *
{
struct ospf_vl_data *vl_data;
- vl_data = XMALLOC (MTYPE_OSPF_VL_DATA, sizeof (struct ospf_vl_data));
- memset (vl_data, 0, sizeof (struct ospf_vl_data));
+ vl_data = XCALLOC (MTYPE_OSPF_VL_DATA, sizeof (struct ospf_vl_data));
vl_data->vl_peer.s_addr = vl_peer.s_addr;
vl_data->vl_area_id = area->area_id;
snprintf (ifname, sizeof(ifname), "VLINK%d", vlink_count);
vi = if_create (ifname, strnlen(ifname, sizeof(ifname)));
+ /*
+ * if_create sets ZEBRA_INTERFACE_LINKDETECTION
+ * virtual links don't need this.
+ */
+ UNSET_FLAG (vi->status, ZEBRA_INTERFACE_LINKDETECTION);
co = connected_new ();
co->ifp = vi;
listnode_add (vi->connected, co);
struct ospf_interface *voi;
struct listnode *node;
struct vertex_parent *vp = NULL;
- int i;
+ unsigned int i;
struct router_lsa *rl;
voi = vl_data->vl_oi;
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_timer_add (ospf->backbone);
+ 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!");
}
return c;
}
-\f
+
struct crypt_key *
ospf_crypt_key_new ()
{
- struct crypt_key *ck;
-
- ck = XMALLOC (MTYPE_OSPF_CRYPT_KEY, sizeof (struct crypt_key));
- memset (ck, 0, sizeof (struct crypt_key));
-
- return ck;
+ return XCALLOC (MTYPE_OSPF_CRYPT_KEY, sizeof (struct crypt_key));
}
void
ospf_if_init ()
{
/* Initialize Zebra interface data structure. */
- if_init ();
- om->iflist = iflist;
+ om->iflist = vrf_iflist (VRF_DEFAULT);
if_add_hook (IF_NEW_HOOK, ospf_if_new_hook);
if_add_hook (IF_DELETE_HOOK, ospf_if_delete_hook);
}