2004-05-05 Paul Jakma <paul@dishone.st>
* ospf_packet.c: (ospf_associate_packet_vl) cleanup, move
some of the checks up to ospf_read, return either a
virtual link oi, or NULL.
(ospf_read) Cleanup, make it responsible for checks. Remove
the nbr lookup - moved to ospf_neighbor. Adjust all nbr
lookups to use new wrappers exported by ospf_neighbor.
* ospf_neighbor.h: Add ospf_neigbour_get and ospf_nbr_lookup.
* ospf_neighbor.c: (ospf_neigbour_get) Index ospf_interface
neighbour table by router-id for virtual-link ospf_interfaces,
not by peer_addr (which breaks for asymmetric vlinks)
(ospf_nbr_lookup) add a wrapper for nbr lookups to deal with
above.
diff --git a/ospfd/ChangeLog b/ospfd/ChangeLog
index 39a1887..6b15fe6 100644
--- a/ospfd/ChangeLog
+++ b/ospfd/ChangeLog
@@ -1,3 +1,18 @@
+2004-05-05 Paul Jakma <paul@dishone.st>
+
+ * ospf_packet.c: (ospf_associate_packet_vl) cleanup, move
+ some of the checks up to ospf_read, return either a
+ virtual link oi, or NULL.
+ (ospf_read) Cleanup, make it responsible for checks. Remove
+ the nbr lookup - moved to ospf_neighbor. Adjust all nbr
+ lookups to use new wrappers exported by ospf_neighbor.
+ * ospf_neighbor.h: Add ospf_neigbour_get and ospf_nbr_lookup.
+ * ospf_neighbor.c: (ospf_neigbour_get) Index ospf_interface
+ neighbour table by router-id for virtual-link ospf_interfaces,
+ not by peer_addr (which breaks for asymmetric vlinks)
+ (ospf_nbr_lookup) add a wrapper for nbr lookups to deal with
+ above.
+
2004-04-22 Hasso Tepper <hasso@estpak.ee>
* ospf_zebra.c: Don't ignore reject/bh routes, it's the only way
diff --git a/ospfd/ospf_neighbor.c b/ospfd/ospf_neighbor.c
index ccef055..6f2d4a0 100644
--- a/ospfd/ospf_neighbor.c
+++ b/ospfd/ospf_neighbor.c
@@ -138,6 +138,11 @@
/* Unlink ospf neighbor from the interface. */
p.family = AF_INET;
p.prefixlen = IPV4_MAX_BITLEN;
+
+ /* vlinks are indexed by router-id */
+ if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
+ p.u.prefix4 = nbr->router_id;
+ else
p.u.prefix4 = nbr->src;
rn = route_node_lookup (oi->nbrs, &p);
@@ -236,6 +241,10 @@
}
#endif /* HAVE_OPAQUE_LSA */
+/* lookup nbr by address - use this only if you know you must
+ * otherwise use the ospf_nbr_lookup() wrapper, which deals
+ * with virtual link neighbours
+ */
struct ospf_neighbor *
ospf_nbr_lookup_by_addr (struct route_table *nbrs,
struct in_addr *addr)
@@ -317,3 +326,99 @@
return;
}
+
+
+struct ospf_neighbor *
+ospf_nbr_lookup (struct ospf_interface *oi, struct ip *iph,
+ struct ospf_header *ospfh)
+{
+ if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
+ return (ospf_nbr_lookup_by_routerid (oi->nbrs, &ospfh->router_id));
+ else
+ return (ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src));
+}
+
+struct ospf_neighbor *
+ospf_nbr_add (struct ospf_interface *oi, struct ospf_header *ospfh,
+ struct prefix *p)
+{
+ struct ospf_neighbor *nbr;
+
+ nbr = ospf_nbr_new (oi);
+ nbr->state = NSM_Down;
+ nbr->src = p->u.prefix4;
+ memcpy (&nbr->address, p, sizeof (struct prefix));
+
+ nbr->nbr_nbma = NULL;
+ if (oi->type == OSPF_IFTYPE_NBMA)
+ {
+ struct ospf_nbr_nbma *nbr_nbma;
+ listnode node;
+
+ for (node = listhead (oi->nbr_nbma); node; nextnode (node))
+ {
+ nbr_nbma = getdata (node);
+ assert (nbr_nbma);
+
+ if (IPV4_ADDR_SAME(&nbr_nbma->addr, &nbr->src))
+ {
+ nbr_nbma->nbr = nbr;
+ nbr->nbr_nbma = nbr_nbma;
+
+ if (nbr_nbma->t_poll)
+ OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
+
+ nbr->state_change = nbr_nbma->state_change + 1;
+ }
+ }
+ }
+
+ /* New nbr, save the crypto sequence number if necessary */
+ if (ntohs (ospfh->auth_type) == OSPF_AUTH_CRYPTOGRAPHIC)
+ nbr->crypt_seqnum = ospfh->u.crypt.crypt_seqnum;
+
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_info ("NSM[%s:%s]: start", IF_NAME (nbr->oi),
+ inet_ntoa (nbr->router_id));
+
+ return nbr;
+}
+
+struct ospf_neighbor *
+ospf_nbr_get (struct ospf_interface *oi, struct ospf_header *ospfh,
+ struct ip *iph, struct prefix *p)
+{
+ struct route_node *rn;
+ struct prefix key;
+ struct ospf_neighbor *nbr;
+
+ key.family = AF_INET;
+ key.prefixlen = IPV4_MAX_BITLEN;
+
+ if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
+ key.u.prefix4 = ospfh->router_id; /* index vlink nbrs by router-id */
+ else
+ key.u.prefix4 = iph->ip_src;
+
+ rn = route_node_get (oi->nbrs, &key);
+ if (rn->info)
+ {
+ route_unlock_node (rn);
+ nbr = rn->info;
+
+ if (oi->type == OSPF_IFTYPE_NBMA && nbr->state == NSM_Attempt)
+ {
+ nbr->src = iph->ip_src;
+ memcpy (&nbr->address, p, sizeof (struct prefix));
+ }
+ }
+ else
+ {
+ rn->info = nbr = ospf_nbr_add (oi, ospfh, p);
+ }
+
+ nbr->router_id = ospfh->router_id;
+
+ return nbr;
+}
+
diff --git a/ospfd/ospf_neighbor.h b/ospfd/ospf_neighbor.h
index f7b1874..f91ef3f 100644
--- a/ospfd/ospf_neighbor.h
+++ b/ospfd/ospf_neighbor.h
@@ -23,6 +23,8 @@
#ifndef _ZEBRA_OSPF_NEIGHBOR_H
#define _ZEBRA_OSPF_NEIGHBOR_H
+#include <ospfd/ospf_packet.h>
+
/* Neighbor Data Structure */
struct ospf_neighbor
{
@@ -93,10 +95,16 @@
void ospf_nbr_delete (struct ospf_neighbor *);
int ospf_nbr_bidirectional (struct in_addr *, struct in_addr *, int);
void ospf_nbr_add_self (struct ospf_interface *);
-int ospf_nbr_count (struct route_table *, int);
+int ospf_nbr_count (struct ospf_interface *, int);
#ifdef HAVE_OPAQUE_LSA
-int ospf_opaque_capable_nbr_count (struct route_table *nbrs, int status);
+int ospf_nbr_count_opaque_capable (struct ospf_interface *);
#endif /* HAVE_OPAQUE_LSA */
+struct ospf_neighbor *ospf_nbr_get (struct ospf_interface *,
+ struct ospf_header *,
+ struct ip *,
+ struct prefix *);
+struct ospf_neighbor *ospf_nbr_lookup (struct ospf_interface *, struct ip *,
+ struct ospf_header *);
struct ospf_neighbor *ospf_nbr_lookup_by_addr (struct route_table *,
struct in_addr *);
struct ospf_neighbor *ospf_nbr_lookup_by_routerid (struct route_table *,
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index 1f8ecd4..e6b2ea7 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -607,9 +607,8 @@
{
struct ospf_hello *hello;
struct ospf_neighbor *nbr;
- struct route_node *rn;
- struct prefix p, key;
int old_state;
+ struct prefix p;
/* increment statistics. */
oi->hello_in++;
@@ -736,70 +735,12 @@
OPTIONS (oi), hello->options);
return;
}
-
-
- /* Get neighbor information from table. */
- key.family = AF_INET;
- key.prefixlen = IPV4_MAX_BITLEN;
- key.u.prefix4 = iph->ip_src;
-
- rn = route_node_get (oi->nbrs, &key);
- if (rn->info)
- {
- route_unlock_node (rn);
- nbr = rn->info;
-
- if (oi->type == OSPF_IFTYPE_NBMA && nbr->state == NSM_Attempt)
- {
- nbr->src = iph->ip_src;
- nbr->address = p;
- }
- }
- else
- {
- /* Create new OSPF Neighbor structure. */
- nbr = ospf_nbr_new (oi);
- nbr->state = NSM_Down;
- nbr->src = iph->ip_src;
- nbr->address = p;
-
- rn->info = nbr;
-
- nbr->nbr_nbma = NULL;
-
- if (oi->type == OSPF_IFTYPE_NBMA)
- {
- struct ospf_nbr_nbma *nbr_nbma;
- listnode node;
-
- for (node = listhead (oi->nbr_nbma); node; nextnode (node))
- {
- nbr_nbma = getdata (node);
- assert (nbr_nbma);
-
- if (IPV4_ADDR_SAME(&nbr_nbma->addr, &iph->ip_src))
- {
- nbr_nbma->nbr = nbr;
- nbr->nbr_nbma = nbr_nbma;
-
- if (nbr_nbma->t_poll)
- OSPF_POLL_TIMER_OFF (nbr_nbma->t_poll);
-
- nbr->state_change = nbr_nbma->state_change + 1;
- }
- }
- }
-
- /* New nbr, save the crypto sequence number if necessary */
- if (ntohs (ospfh->auth_type) == OSPF_AUTH_CRYPTOGRAPHIC)
- nbr->crypt_seqnum = ospfh->u.crypt.crypt_seqnum;
-
- if (IS_DEBUG_OSPF_EVENT)
- zlog_info ("NSM[%s:%s]: start", IF_NAME (nbr->oi),
- inet_ntoa (nbr->router_id));
- }
- nbr->router_id = ospfh->router_id;
+ /* get neighbour struct */
+ nbr = ospf_nbr_get (oi, ospfh, iph, &p);
+
+ /* neighbour must be valid, ospf_nbr_get creates if none existed */
+ assert (nbr);
old_state = nbr->state;
@@ -1029,7 +970,7 @@
dd = (struct ospf_db_desc *) STREAM_PNT (s);
- nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src);
+ nbr = ospf_nbr_lookup (oi, iph, ospfh);
if (nbr == NULL)
{
zlog_warn ("Packet[DD]: Unknown Neighbor %s",
@@ -1286,7 +1227,7 @@
/* Increment statistics. */
oi->ls_req_in++;
- nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src);
+ nbr = ospf_nbr_lookup (oi, iph, ospfh);
if (nbr == NULL)
{
zlog_warn ("Link State Request: Unknown Neighbor %s.",
@@ -1520,7 +1461,7 @@
oi->ls_upd_in++;
/* Check neighbor. */
- nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src);
+ nbr = ospf_nbr_lookup (oi, iph, ospfh);
if (nbr == NULL)
{
zlog_warn ("Link State Update: Unknown Neighbor %s on int: %s",
@@ -1881,7 +1822,7 @@
/* increment statistics. */
oi->ls_ack_in++;
- nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &iph->ip_src);
+ nbr = ospf_nbr_lookup (oi, iph, ospfh);
if (nbr == NULL)
{
zlog_warn ("Link State Acknowledgment: Unknown Neighbor %s.",
@@ -2043,8 +1984,7 @@
}
struct ospf_interface *
-ospf_associate_packet_vl (struct ospf *ospf,
- struct interface *ifp, struct ospf_interface *oi,
+ospf_associate_packet_vl (struct ospf *ospf, struct interface *ifp,
struct ip *iph, struct ospf_header *ospfh)
{
struct ospf_interface *rcv_oi;
@@ -2054,14 +1994,16 @@
if (IN_MULTICAST (ntohl (iph->ip_dst.s_addr)) ||
!OSPF_IS_AREA_BACKBONE (ospfh))
- return oi;
+ return NULL;
- if ((rcv_oi = oi) == NULL)
- {
- if ((rcv_oi = ospf_if_lookup_by_local_addr (ospf, NULL,
- iph->ip_dst)) == NULL)
- return NULL;
- }
+ /* look for local OSPF interface matching the destination
+ * to determine Area ID. We presume therefore the destination address
+ * is unique, or at least (for "unnumbered" links), not used in other
+ * areas
+ */
+ if ((rcv_oi = ospf_if_lookup_by_local_addr (ospf, NULL,
+ iph->ip_dst)) == NULL)
+ return NULL;
for (node = listhead (ospf->vlinks); node; nextnode (node))
{
@@ -2092,7 +2034,7 @@
if (IS_DEBUG_OSPF_EVENT)
zlog_info ("couldn't find any VL to associate the packet with");
- return oi;
+ return NULL;
}
int
@@ -2287,6 +2229,12 @@
if (ibuf == NULL)
return -1;
+ if (ifp == NULL)
+ {
+ stream_free (ibuf);
+ return 0;
+ }
+
iph = (struct ip *) STREAM_DATA (ibuf);
/* prepare for next packet. */
@@ -2316,26 +2264,36 @@
/* associate packet with ospf interface */
oi = ospf_if_lookup_recv_if (ospf, iph->ip_src);
- if (ifp && oi && oi->ifp != ifp)
+
+ /* if no local ospf_interface,
+ * or header area is backbone but ospf_interface is not
+ * check for VLINK interface
+ */
+ if ( (oi == NULL) ||
+ (OSPF_IS_AREA_ID_BACKBONE(ospfh->area_id)
+ && !OSPF_IS_AREA_ID_BACKBONE(oi->area->area_id))
+ )
+ {
+ if ((oi = ospf_associate_packet_vl (ospf, ifp, iph, ospfh)) == NULL)
+ {
+ zlog_warn ("Packet from [%s] received on link %s"
+ " but no ospf_interface",
+ inet_ntoa (iph->ip_src), ifp->name);
+ stream_free (ibuf);
+ return 0;
+ }
+ }
+
+ /* else it must be a local ospf interface, check it was received on
+ * correct link
+ */
+ else if (oi->ifp != ifp)
{
zlog_warn ("Packet from [%s] received on wrong link %s",
inet_ntoa (iph->ip_src), ifp->name);
stream_free (ibuf);
return 0;
}
-
- if ((oi = ospf_associate_packet_vl (ospf, ifp, oi, iph, ospfh)) == NULL)
- {
- if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
- {
- zlog_info ("ospf_read[%s/%s]: Could not associate packet with VL, "
- "dropping.",
- ospf_packet_type_str[ospfh->type],
- inet_ntoa (iph->ip_src));
- }
- stream_free (ibuf);
- return 0;
- }
/*
* If the received packet is destined for AllDRouters, the packet