From d3f0d6210119ff520c286c89bd614838cc6cbf8e Mon Sep 17 00:00:00 2001 From: paul Date: Wed, 5 May 2004 15:27:15 +0000 Subject: 2004-05-05 Paul Jakma * 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. --- ospfd/ChangeLog | 15 ++++++ ospfd/ospf_neighbor.c | 105 ++++++++++++++++++++++++++++++++++++ ospfd/ospf_neighbor.h | 12 ++++- ospfd/ospf_packet.c | 144 ++++++++++++++++++-------------------------------- 4 files changed, 181 insertions(+), 95 deletions(-) (limited to 'ospfd') diff --git a/ospfd/ChangeLog b/ospfd/ChangeLog index 39a18879..6b15fe64 100644 --- a/ospfd/ChangeLog +++ b/ospfd/ChangeLog @@ -1,3 +1,18 @@ +2004-05-05 Paul Jakma + + * 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 * 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 ccef0559..6f2d4a05 100644 --- a/ospfd/ospf_neighbor.c +++ b/ospfd/ospf_neighbor.c @@ -138,6 +138,11 @@ ospf_nbr_delete (struct ospf_neighbor *nbr) /* 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 @@ ospf_nbr_count_opaque_capable (struct ospf_interface *oi) } #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 @@ ospf_renegotiate_optional_capabilities (struct ospf *top) 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 f7b18742..f91ef3f9 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 + /* Neighbor Data Structure */ struct ospf_neighbor { @@ -93,10 +95,16 @@ void ospf_nbr_free (struct ospf_neighbor *); 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 1f8ecd46..e6b2ea7c 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -607,9 +607,8 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, { 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 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh, 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 @@ ospf_db_desc (struct ip *iph, struct ospf_header *ospfh, 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 @@ ospf_ls_req (struct ip *iph, struct ospf_header *ospfh, /* 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 @@ ospf_ls_upd (struct ip *iph, struct ospf_header *ospfh, 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 @@ ospf_ls_ack (struct ip *iph, struct ospf_header *ospfh, /* 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 @@ ospf_recv_packet (int fd, struct interface **ifp) } 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 @@ ospf_associate_packet_vl (struct ospf *ospf, 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 @@ ospf_associate_packet_vl (struct ospf *ospf, 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 @@ ospf_read (struct thread *thread) if (ibuf == NULL) return -1; + if (ifp == NULL) + { + stream_free (ibuf); + return 0; + } + iph = (struct ip *) STREAM_DATA (ibuf); /* prepare for next packet. */ @@ -2316,23 +2264,33 @@ ospf_read (struct thread *thread) /* associate packet with ospf interface */ oi = ospf_if_lookup_recv_if (ospf, iph->ip_src); - if (ifp && oi && 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 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 (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV)) + if ((oi = ospf_associate_packet_vl (ospf, ifp, iph, ospfh)) == NULL) { - zlog_info ("ospf_read[%s/%s]: Could not associate packet with VL, " - "dropping.", - ospf_packet_type_str[ospfh->type], - inet_ntoa (iph->ip_src)); + 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; } -- cgit v1.2.1