[quagga-dev 1077] point-to-point patch

Andrew J. Schorr aschorr at telemetry-investments.com
Mon Apr 26 21:16:43 BST 2004


Hi,

I am attaching a patch to enhance quagga support for point-to-point
interfaces.  Based on my (perhaps incomplete) understanding of
the current code, it is mostly designed to support PtP connections
where the local and peer addresses are borrowed from other interfaces
and specified with a /32 netmask.  In the case where one wants to
have a specifically assigned subnet (typically /30) for a PtP link
(not sharing IP addresses with other interfaces), quagga does not
seem to work.  Under linux using the iproute2 tools, it is certainly
possible to assign a subnet to a PtP link, and it is optional whether
to specify a peer address in such a case.  This patch gets quagga
to support that scenario.

The zebra daemon allows for the possibility of a PtP interface
where the local address is present, but not the peer address.
However, in zebra/zserv.c:zsend_interface_address_add(), the code
translates a NULL destination address pointer into a 0.0.0.0 address.
So the child daemons (e.g. ripd, or ospfd) never receive the
destination address as a NULL pointer, instead they get 0.0.0.0.
So my patch fixes that problem.

Also, in zebra/rt_netlink.c:netlink_interface_addr(), I had to add a
memcmp to ignore the peer address when it's the same as the
local address (this is copied from iproute2/ip/ipaddress.c:print_addrinfo().
Without that patch, zebra thinks that the local address is also the peer
address in the situation where a peer address was never assigned.

Other than that, it's a question of patching the lib and daemon directories
to stop assuming that the connected->destination pointer is non-NULL.
This involves some minor patches to ripd and bgpd (not tested),
and some more significant patches to ospfd.

In general, my patches get the code to behave the same as it 
did before if the connected->destination address is present and the
prefixlen is IPV4_MAX_PREFIXLEN (32).  If the destination address
is missing, or the prefixlen is not 32, then it is assumed that a
specific subnet has been dedicated to the PtP link, and the PtP
interface is not identified by the peer address.

Most of the changes to ospfd were to add more debugging statements so
that I could see what was going on.  The signicant changes were in
ospf_interface.c to define a new function ospf_if_is_connected,
and then to ospf_spf.c:ospf_nexthop_calculation() to call the new
function instead of ospf_if_is_configured().  And I patched
ospf_lsa.c:lsa_link_ptop_set() to ignore the destination address
if the prefixlen is not 32.

So with this patch, one now has the option of configuring the PtP
interface with a dedicated subnet, just as is possible with Cisco IOS.
In that scenario, one no longer has the strange routes through the
remote router to the local PtP interface.

This patch was developed against quagga-0.96.4 under Linux 2.4.22.
I then forward-ported it to apply against this morning's CVS snapshot.
I have not tested with the CVS code, but it does compile.

I hope somebody finds this patch helpful, and it would be great if it
could be integrated into CVS.  I am very interested in any comments you
may have, positive or negative; I know this is very desirable functionality
for our site, and I hope others are interested.

-Andy
-------------- next part --------------
--- ./lib/if.c.ptp	2003-12-21 04:51:42.000000000 -0500
+++ ./lib/if.c	2004-04-26 13:57:01.000000000 -0400
@@ -245,7 +245,7 @@
 {
   listnode node;
   struct prefix addr;
-  struct prefix best;
+  int bestlen;
   listnode cnode;
   struct interface *ifp;
   struct prefix *p;
@@ -254,7 +254,7 @@
 
   /* Zero structures - get rid of rubbish from stack */
   memset(&addr, 0, sizeof(addr));
-  memset(&best, 0, sizeof(best));
+  bestlen = 0;
 
   addr.family = AF_INET;
   addr.u.prefix4 = src;
@@ -270,31 +270,23 @@
 	{
 	  c = getdata (cnode);
 
-	  if (if_is_pointopoint (ifp))
+	  if (c->address && (c->address->family == AF_INET))
 	    {
-	      p = c->address;
-
-	      if (p && p->family == AF_INET)
+	      if (if_is_pointopoint (ifp) && c->destination &&
+		  (c->address->prefixlen == IPV4_MAX_PREFIXLEN))
 		{
-#ifdef OLD_RIB	 /* PTP  links are conventionally identified 
-		     by the address of the far end - MAG */
-		  if (IPV4_ADDR_SAME (&p->u.prefix4, &src))
-		    return ifp;
-#endif
-		  p = c->destination;
-		  if (p && IPV4_ADDR_SAME (&p->u.prefix4, &src))
+		 /* PTP  links are conventionally identified 
+		    by the address of the far end - MAG */
+		  if (IPV4_ADDR_SAME (&c->destination->u.prefix4, &src))
 		    return ifp;
 		}
-	    }
-	  else
-	    {
-	      p = c->address;
-
-	      if (p->family == AF_INET)
+	      else
 		{
-		  if (prefix_match (p, &addr) && p->prefixlen > best.prefixlen)
+		  p = c->address;
+
+		  if (prefix_match (p, &addr) && p->prefixlen > bestlen)
 		    {
-		      best = *p;
+		      bestlen = p->prefixlen;
 		      match = ifp;
 		    }
 		}
@@ -656,7 +648,7 @@
 connected_lookup_address (struct interface *ifp, struct in_addr dst)
 {
   struct prefix addr;
-  struct prefix best;
+  int bestlen;
   listnode cnode;
   struct prefix *p;
   struct connected *c;
@@ -664,7 +656,7 @@
 
   /* Zero structures - get rid of rubbish from stack */
   memset(&addr, 0, sizeof(addr));
-  memset(&best, 0, sizeof(best));
+  bestlen = 0;
 
   addr.family = AF_INET;
   addr.u.prefix4 = dst;
@@ -676,35 +668,27 @@
     {
       c = getdata (cnode);
 
-      if (if_is_pointopoint (ifp))
-	{
-	  p = c->address;
-
-	  if (p && p->family == AF_INET)
+      if (c->address && (c->address->family == AF_INET))
+        {
+	  if (if_is_pointopoint (ifp) && c->destination &&
+	      (c->address->prefixlen == IPV4_MAX_PREFIXLEN))
 	    {
-#ifdef OLD_RIB	 /* PTP  links are conventionally identified 
-		    by the address of the far end - MAG */
-	      if (IPV4_ADDR_SAME (&p->u.prefix4, &dst))
-		return c;
-#endif
-	      p = c->destination;
-	      if (p && IPV4_ADDR_SAME (&p->u.prefix4, &dst))
+		     /* PTP  links are conventionally identified 
+			by the address of the far end - MAG */
+	      if (IPV4_ADDR_SAME (&c->destination->u.prefix4, &dst))
 		return c;
 	    }
-	}
-      else
-	{
-	  p = c->address;
-
-	  if (p->family == AF_INET)
+	  else
 	    {
-	      if (prefix_match (p, &addr) && p->prefixlen > best.prefixlen)
+	      p = c->address;
+
+	      if (prefix_match (p, &addr) && p->prefixlen > bestlen)
 		{
-		  best = *p;
+		  bestlen = p->prefixlen;
 		  match = c;
 		}
 	    }
-	}
+        }
     }
   return match;
 }
--- ./lib/zclient.c.ptp	2004-02-13 12:44:50.000000000 -0500
+++ ./lib/zclient.c	2004-04-26 13:57:01.000000000 -0400
@@ -649,14 +649,18 @@
   ifc->address = p;
 
   /* Fetch destination address. */
-  p = prefix_new ();
-  stream_get (&p->u.prefix, s, plen);
-  p->family = family;
+  if (stream_getc (s) != 0)
+    {
+      p = prefix_new ();
+      stream_get (&p->u.prefix, s, plen);
+      p->family = family;
+    }
+  else
+    /* no destination address */
+    p = NULL;
 
   ifc->destination = p;
 
-  p = ifc->address;
-
   /* Add connected address to the interface. */
   listnode_add (ifp->connected, ifc);
 
@@ -697,8 +701,12 @@
   p.prefixlen = stream_getc (s);
 
   /* Fetch destination address. */
-  stream_get (&d.u.prefix, s, len);
-  d.family = family;
+  if (stream_getc (s) != 0)
+    {
+      /* but why?  this information is not used... */
+      stream_get (&d.u.prefix, s, len);
+      d.family = family;
+    }
 
   ifc = connected_delete_by_prefix (ifp, &p);
 
--- ./lib/prefix.h.ptp	2004-01-13 09:55:40.000000000 -0500
+++ ./lib/prefix.h	2004-04-26 13:57:01.000000000 -0400
@@ -143,6 +143,10 @@
 void masklen2ip (int, struct in_addr *);
 void apply_classful_mask_ipv4 (struct prefix_ipv4 *);
 
+/* given the address of a host on a network and the network mask length,
+   calculate the broadcast address for that network */
+in_addr_t ipv4_broadcast_addr (in_addr_t hostaddr, int masklen);
+
 char *prefix_family_str (struct prefix *p);
 struct prefix *sockunion2prefix ();
 struct prefix *sockunion2hostprefix ();
--- ./lib/prefix.c.ptp	2004-01-13 09:55:40.000000000 -0500
+++ ./lib/prefix.c	2004-04-26 13:57:01.000000000 -0400
@@ -664,6 +664,15 @@
     }
 }
 
+in_addr_t
+ipv4_broadcast_addr (in_addr_t hostaddr, int masklen)
+{
+  struct in_addr mask;
+
+  masklen2ip (masklen, &mask);
+  return hostaddr | ~mask.s_addr;
+}
+
 /* Utility function to convert ipv4 netmask to prefixes 
    ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16"
    ex.) "1.0.0.0" NULL => "1.0.0.0/8"                   */
--- ./zebra/zserv.c.ptp	2004-04-06 07:59:00.000000000 -0400
+++ ./zebra/zserv.c	2004-04-26 13:57:01.000000000 -0400
@@ -284,9 +284,12 @@
   /* Destination. */
   p = ifc->destination;
   if (p)
-    stream_put (s, &p->u.prefix, blen);
+    {
+      stream_putc (s, 1);
+      stream_put (s, &p->u.prefix, blen);
+    }
   else
-    stream_put (s, NULL, blen);
+    stream_putc (s, 0);
 
   /* Write packet size. */
   stream_putw_at (s, 0, stream_get_endp (s));
@@ -330,9 +333,12 @@
 
   p = ifc->destination;
   if (p)
-    stream_put (s, &p->u.prefix, blen);
+    {
+      stream_putc (s, 1);
+      stream_put (s, &p->u.prefix, blen);
+    }
   else
-    stream_put (s, NULL, blen);
+    stream_putc (s, 0);
 
   /* Write packet size. */
   stream_putw_at (s, 0, stream_get_endp (s));
--- ./zebra/rt_netlink.c.ptp	2004-04-06 08:07:06.000000000 -0400
+++ ./zebra/rt_netlink.c	2004-04-26 13:57:01.000000000 -0400
@@ -554,7 +554,9 @@
       if (tb[IFA_LOCAL])
         {
           addr = RTA_DATA (tb[IFA_LOCAL]);
-          if (tb[IFA_ADDRESS])
+          if (tb[IFA_ADDRESS] &&
+	      memcmp(RTA_DATA(tb[IFA_ADDRESS]),RTA_DATA(tb[IFA_LOCAL]),4))
+	    /* if IFA_ADDRESS != IFA_LOCAL, then it's the peer address */
             broad = RTA_DATA (tb[IFA_ADDRESS]);
           else
             broad = NULL;
--- ./zebra/connected.c.ptp	2003-10-13 04:59:40.000000000 -0400
+++ ./zebra/connected.c	2004-04-26 13:57:01.000000000 -0400
@@ -115,6 +115,43 @@
       p->family = AF_INET;
       p->prefix = *broad;
       ifc->destination = (struct prefix *) p;
+
+      /* validate the destination address */
+      if (ifp->flags & IFF_POINTOPOINT)
+        {
+	  if (IPV4_ADDR_SAME(addr,broad))
+	    zlog_warn("warning: PtP interface %s has same local and peer "
+		      "address %s, routing protocols may malfunction",
+		      ifp->name,inet_ntoa(*addr));
+	  else if ((prefixlen != IPV4_MAX_PREFIXLEN) &&
+	   	   (ipv4_broadcast_addr(addr->s_addr,prefixlen) !=
+	   	    ipv4_broadcast_addr(broad->s_addr,prefixlen)))
+	    {
+	      char buf[2][INET_ADDRSTRLEN];
+	      zlog_warn("warning: PtP interface %s network mismatch: local "
+	      		"%s/%d vs. peer %s, routing protocols may malfunction",
+	    		ifp->name,
+			inet_ntop (AF_INET, addr, buf[0], sizeof(buf[0])),
+			prefixlen,
+			inet_ntop (AF_INET, broad, buf[1], sizeof(buf[1])));
+	    }
+        }
+      else
+        {
+	  if (broad->s_addr != ipv4_broadcast_addr(addr->s_addr,prefixlen))
+	    {
+	      char buf[2][INET_ADDRSTRLEN];
+	      struct in_addr bcalc;
+	      bcalc.s_addr = ipv4_broadcast_addr(addr->s_addr,prefixlen);
+	      zlog_warn("warning: interface %s broadcast addr %s/%d != "
+	       		"calculated %s, routing protocols may malfunction",
+	    		ifp->name,
+			inet_ntop (AF_INET, broad, buf[0], sizeof(buf[0])),
+			prefixlen,
+			inet_ntop (AF_INET, &bcalc, buf[1], sizeof(buf[1])));
+	    }
+        }
+
     }
 
   /* Label of this address. */
--- ./zebra/interface.c.ptp	2004-03-18 10:40:33.000000000 -0500
+++ ./zebra/interface.c	2004-04-26 13:57:01.000000000 -0400
@@ -925,7 +925,6 @@
   struct prefix_ipv4 cp;
   struct connected *ifc;
   struct prefix_ipv4 *p;
-  struct in_addr mask;
   int ret;
 
   ret = str2prefix_ipv4 (addr_str, &cp);
@@ -951,8 +950,7 @@
 	{
 	  p = prefix_ipv4_new ();
 	  *p = cp;
-	  masklen2ip (p->prefixlen, &mask);
-	  p->prefix.s_addr |= ~mask.s_addr;
+	  p->prefix.s_addr = ipv4_broadcast_addr(p->prefix.s_addr,p->prefixlen);
 	  ifc->destination = (struct prefix *) p;
 	}
 
--- ./bgpd/bgp_nexthop.c.ptp	2004-03-04 12:45:00.000000000 -0500
+++ ./bgpd/bgp_nexthop.c	2004-04-26 13:57:01.000000000 -0400
@@ -666,7 +666,7 @@
       p.family = AF_INET;
       p.prefixlen = addr->prefixlen;
 
-      if (if_is_pointopoint (ifp))
+      if (if_is_pointopoint (ifp) && dest)
 	p.u.prefix4 = dest->u.prefix4;
       else
 	p.u.prefix4 = addr->u.prefix4;
@@ -697,7 +697,7 @@
       p.family = AF_INET6;
       p.prefixlen = addr->prefixlen;
 
-      if (if_is_pointopoint (ifp))
+      if (if_is_pointopoint (ifp) && dest)
 	p.u.prefix6 = dest->u.prefix6;
       else
 	p.u.prefix6 = addr->u.prefix6;
@@ -751,7 +751,7 @@
       p.family = AF_INET;
       p.prefixlen = addr->prefixlen;
 
-      if (if_is_pointopoint (ifp))
+      if (if_is_pointopoint (ifp) && dest)
 	p.u.prefix4 = dest->u.prefix4;
       else
 	p.u.prefix4 = addr->u.prefix4;
@@ -782,7 +782,7 @@
       p.family = AF_INET6;
       p.prefixlen = addr->prefixlen;
 
-      if (if_is_pointopoint (ifp))
+      if (if_is_pointopoint (ifp) && dest)
 	p.u.prefix6 = dest->u.prefix6;
       else
 	p.u.prefix6 = addr->u.prefix6;
--- ./ripd/ripd.c.ptp	2004-03-17 21:40:55.000000000 -0500
+++ ./ripd/ripd.c	2004-04-26 13:57:01.000000000 -0400
@@ -2333,7 +2333,6 @@
 rip_update_interface (struct interface *ifp, u_char version, int route_type,
                       struct connected *sconn)
 {
-  struct prefix_ipv4 *p;
   struct connected *connected;
   listnode node;
   struct sockaddr_in to;
@@ -2357,15 +2356,18 @@
 	{	    
 	  connected = getdata (node);
 
-	  /* Fetch broadcast address or poin-to-point destination
-             address . */
-	  p = (struct prefix_ipv4 *) connected->destination;
-
-	  if (p->family == AF_INET)
+	  if (connected->address->family == AF_INET)
 	    {
 	      /* Destination address and port setting. */
 	      memset (&to, 0, sizeof (struct sockaddr_in));
-	      to.sin_addr = p->prefix;
+	      if (connected->destination)
+		/* use specified broadcast or point-to-point destination addr */
+	        to.sin_addr = connected->destination->u.prefix4;
+	      else
+		/* calculate the appropriate broadcast address */
+	        to.sin_addr.s_addr =
+		  ipv4_broadcast_addr(connected->address->u.prefix4.s_addr,
+				      connected->address->prefixlen);
 	      to.sin_port = htons (RIP_PORT_DEFAULT);
 
 	      if (IS_RIP_DEBUG_EVENT)
--- ./ripd/rip_interface.c.ptp	2004-01-23 10:31:42.000000000 -0500
+++ ./ripd/rip_interface.c	2004-04-26 15:21:32.000000000 -0400
@@ -148,7 +148,8 @@
 
   if (connected != NULL) 
     {
-  if (if_pointopoint)
+  if (if_pointopoint && connected->destination &&
+      (connected->address->prefixlen == IPV4_MAX_PREFIXLEN))
     p = (struct prefix_ipv4 *) connected->destination;
   else
       p = (struct prefix_ipv4 *) connected->address;
@@ -161,7 +162,9 @@
 
   if (setsockopt_multicast_ipv4 (sock, IP_MULTICAST_IF, addr, 0, 0) < 0) 
 	    {
-	      zlog_warn ("Can't setsockopt IP_MULTICAST_IF to fd %d", sock);
+	      zlog_warn ("Can't setsockopt IP_MULTICAST_IF on fd %d to "
+	      		 "source address %s for interface %s",
+			 sock, inet_ntoa(addr),connected->ifp->name);
 	      return;
 	    }
 
@@ -190,7 +193,11 @@
   ret = bind (sock, (struct sockaddr *) & from, sizeof (struct sockaddr_in));
 	  if (ret < 0)
 	    {
-	      zlog_warn ("Can't bind socket: %s", strerror (errno));
+	      zlog_warn ("Can't bind socket fd %d to %s port %d for "
+	      		 "interface %s: %s",
+	      		 sock,inet_ntoa(from.sin_addr),
+			 (int)ntohs(from.sin_port),connected->ifp->name,
+			 strerror (errno));
 	    }
 
     if (ripd_privs.change (ZPRIVS_LOWER))
@@ -227,17 +234,22 @@
 
       for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
 	{
-	  struct prefix_ipv4 *p;
 	  struct connected *connected;
 
 	  connected = getdata (cnode);
-	  p = (struct prefix_ipv4 *) connected->destination;
 
-	  if (p->family == AF_INET)
+	  if (connected->address->family == AF_INET)
 	    {
 	      memset (&to, 0, sizeof (struct sockaddr_in));
 	      to.sin_port = htons (RIP_PORT_DEFAULT);
-	      to.sin_addr = p->prefix;
+              if (connected->destination)
+                /* use specified broadcast or point-to-point destination addr */
+                to.sin_addr = connected->destination->u.prefix4;
+              else
+	        /* calculate the appropriate broadcast address */
+                to.sin_addr.s_addr =
+		  ipv4_broadcast_addr(connected->address->u.prefix4.s_addr,
+				      connected->address->prefixlen);
 
 	      if (IS_RIP_DEBUG_EVENT)
 		zlog_info ("SEND request to %s", inet_ntoa (to.sin_addr));
@@ -437,6 +449,11 @@
   listnode node;
   struct connected *connected = NULL;
   struct prefix_ipv4 *p;
+  struct prefix_ipv4 pa;
+
+  pa.family = AF_INET;
+  pa.prefix = addr;
+  pa.prefixlen = IPV4_MAX_BITLEN;
 
   for (node = listhead (iflist); node; nextnode (node))
     {
@@ -447,9 +464,6 @@
 
       for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))
 	{
-	  struct prefix *pxn = NULL; /* Prefix of the neighbor */
-	  struct prefix *pxc = NULL; /* Prefix of the connected network */
-
 	  connected = getdata (cnode);
 
 	  if (if_is_pointopoint (ifp))
@@ -462,34 +476,23 @@
 		    return 1;
 
 		  p = (struct prefix_ipv4 *) connected->destination;
-		  if (p && IPV4_ADDR_SAME (&p->prefix, &addr))
-		    return 1;
+		  if (p)
+		    {
+		      if (IPV4_ADDR_SAME (&p->prefix, &addr))
+			return 1;
+		    }
+		  else
+		    {
+		      if (prefix_match(connected->address,(struct prefix *)&pa))
+			return 1;
+		    }
 		}
 	    }
 	  else
 	    {
-	      p = (struct prefix_ipv4 *) connected->address;
-
-	      if (p->family != AF_INET)
-		continue;
-
-	      pxn = prefix_new();
-	      pxn->family = AF_INET;
-	      pxn->prefixlen = 32;
-	      pxn->u.prefix4 = addr;
-	      
-	      pxc = prefix_new();
-	      prefix_copy(pxc, (struct prefix *) p);
-	      apply_mask(pxc);
-	  
-	      if (prefix_match (pxc, pxn)) 
-		{
-		  prefix_free (pxn);
-		  prefix_free (pxc);
-		  return 1;
-		}
-	      prefix_free(pxc);
-	      prefix_free(pxn);
+	      if ((connected->address->family == AF_INET) &&
+		  prefix_match(connected->address,(struct prefix *)&pa))
+		return 1;
 	    }
 	}
     }
--- ./ospfd/ospf_vty.c.ptp	2004-04-19 14:26:53.000000000 -0400
+++ ./ospfd/ospf_vty.c	2004-04-26 13:57:01.000000000 -0400
@@ -2565,6 +2565,11 @@
       vty_out (vty, "  Internet Address %s/%d,",
 	       inet_ntoa (oi->address->u.prefix4), oi->address->prefixlen);
 
+      if (oi->connected->destination)
+	 vty_out (vty, " %s %s,",
+		  ((ifp->flags & IFF_POINTOPOINT) ? "Peer" : "Broadcast"),
+		  inet_ntoa (oi->connected->destination->u.prefix4));
+
       vty_out (vty, " Area %s%s", ospf_area_desc_string (oi->area),
 	       VTY_NEWLINE);
 
--- ./ospfd/ospf_snmp.c.ptp	2003-09-29 15:54:54.000000000 -0400
+++ ./ospfd/ospf_snmp.c	2004-04-26 13:57:01.000000000 -0400
@@ -1440,7 +1440,8 @@
   /* Lookup first IPv4 address entry. */
   LIST_LOOP (ifp->connected, ifc, nn)
     {
-      if (if_is_pointopoint (ifp))
+      if (if_is_pointopoint (ifp) && ifc->destination &&
+	  (ifc->address->prefixlen == IPV4_MAX_PREFIXLEN))
 	p = ifc->destination;
       else
 	p = ifc->address;
--- ./ospfd/ospfd.c.ptp	2004-04-20 13:25:12.000000000 -0400
+++ ./ospfd/ospfd.c	2004-04-26 15:23:27.000000000 -0400
@@ -714,12 +714,14 @@
    *   PtP special case: network specified == iface peer addr -> ospf
    */
 
-  /* For PtP, match if peer address matches network address exactly.
-   * This can be addr/32 or addr/p for p < 32, but the addr must match
-   * exactly; this is not a test for falling within the prefix.  This
+  /* For PtP, match if peer address matches network address exactly
+   * in situations where the peer address is available and the prefix
+   * length is 32 (i.e. a dedicated subnet has not been assigned).
+   * This is not a test for falling within the prefix.  This
    * test is solely for compatibility with zebra.
-  */
-  if (if_is_pointopoint (co->ifp) && 
+   */
+  if (if_is_pointopoint (co->ifp) && co->destination &&
+      (co->address->prefixlen == IPV4_MAX_PREFIXLEN) &&
       IPV4_ADDR_SAME ( &(co->destination->u.prefix4), &(net->u.prefix4)))
     return 1;
 
@@ -776,7 +778,8 @@
           if (CHECK_FLAG(co->flags,ZEBRA_IFA_SECONDARY))
             continue;
 
-	  if (if_is_pointopoint (co->ifp))
+	  if (if_is_pointopoint (co->ifp) && co->destination &&
+	      (co->address->prefixlen == IPV4_MAX_PREFIXLEN))
 	    addr = co->destination;
 	  else 
 	    addr = co->address;
--- ./ospfd/ospf_spf.c.ptp	2004-04-08 03:43:45.000000000 -0400
+++ ./ospfd/ospf_spf.c	2004-04-26 13:57:01.000000000 -0400
@@ -125,8 +125,17 @@
       nh = (struct vertex_nexthop *) getdata (node);
 
       /* No need to add two links from the same parent. */
-      if (listnode_lookup (nh->parent->child, v) == NULL)
+      if (listnode_lookup (nh->parent->child, v) == NULL) {
         listnode_add (nh->parent->child, v);
+        if (IS_DEBUG_OSPF_EVENT) {
+	  char buf1[INET_ADDRSTRLEN], buf2[INET_ADDRSTRLEN];
+	  zlog_info ("ospf_vertex_add_parent: added vertex %s [type %u] "
+		     "as child of %s",
+		     inet_ntop (AF_INET, &v->id, buf1, sizeof(buf1)),
+		     (u_int)(v->type),
+		     inet_ntop (AF_INET, &nh->parent->id, buf2, sizeof(buf2)));
+        }
+      }
     }
 }
 
@@ -384,8 +393,15 @@
   struct router_lsa_link *l = NULL;
 
 
-  if (IS_DEBUG_OSPF_EVENT)
-    zlog_info ("ospf_nexthop_calculation(): Start");
+  if (IS_DEBUG_OSPF_EVENT) {
+    char buf[4][INET_ADDRSTRLEN];
+    zlog_info ("ospf_nexthop_calculation(): Start for area %s, v %s, w %s, area->spf %s, w->type %u",
+	       inet_ntop (AF_INET, &area->area_id, buf[0], sizeof(buf[0])),
+	       inet_ntop (AF_INET, &v->id, buf[1], sizeof(buf[1])),
+	       inet_ntop (AF_INET, &w->id, buf[2], sizeof(buf[2])),
+	       inet_ntop (AF_INET, &area->spf->id, buf[3], sizeof(buf[3])),
+	       (u_int)w->type);
+  }
 
   /* W's parent is root. */
   if (v == area->spf)
@@ -396,11 +412,20 @@
             {
               struct router_lsa_link *l2 = NULL;
 
+	      if (IS_DEBUG_OSPF_EVENT) {
+		char buf[2][INET_ADDRSTRLEN];
+	        zlog_info("ospf_nexthop_calculation: lsa link id %s, "
+			  "data %s, type %u",
+			  inet_ntop(AF_INET,&l->link_id,buf[0],sizeof(buf[0])),
+			 inet_ntop(AF_INET,&l->link_data,buf[1],sizeof(buf[1])),
+			  (u_int)(l->m[0].type));
+	      }
+
               if (l->m[0].type == LSA_LINK_TYPE_POINTOPOINT)
                 {
                   /* Check for PtMP, signified by PtP link V->W
                      with link_data our PtMP interface. */
-                  oi = ospf_if_is_configured (area->ospf, &l->link_data);
+                  oi = ospf_if_is_connected (area->ospf, &l->link_data);
                   if (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
                     {
                       struct prefix_ipv4 la;
@@ -421,8 +446,23 @@
                     {
                       while ((l2 = ospf_get_next_link (w, v, l2)))
                         {
-                          oi = ospf_if_is_configured (area->ospf,
-                                                      &(l2->link_data));
+                          oi = ospf_if_is_connected (area->ospf,
+                                                     &(l2->link_data));
+
+			  if (IS_DEBUG_OSPF_EVENT) {
+			    char buf[3][INET_ADDRSTRLEN];
+			    zlog_info("ospf_nexthop_calculation: l2 id %s, "
+				      "data %s, oi %s, oi addr %s",
+				      inet_ntop(AF_INET,&l2->link_id,
+				      		buf[0],sizeof(buf[0])),
+				      inet_ntop(AF_INET,&l2->link_data,
+				     		buf[1],sizeof(buf[1])),
+			  	      (oi ? oi->ifp->name : "-"),
+				      (oi ?
+				       inet_ntop(AF_INET,
+				       		 &oi->address->u.prefix4,
+				     		 buf[2],sizeof(buf[2])) : "-"));
+			  }
 
                           if (oi == NULL)
                             continue;
@@ -449,7 +489,7 @@
         {
           while ((l = ospf_get_next_link (v, w, l)))
             {
-              oi = ospf_if_is_configured (area->ospf, &(l->link_data));
+              oi = ospf_if_is_connected (area->ospf, &(l->link_data));
               if (oi)
                 {
                   nh = vertex_nexthop_new (v);
@@ -582,7 +622,7 @@
               if (w_lsa)
                 {
                   if (IS_DEBUG_OSPF_EVENT)
-                    zlog_info ("found the LSA");
+                    zlog_info ("found the LSA for %s",inet_ntoa (l->link_id));
                 }
               break;
             case LSA_LINK_TYPE_TRANSIT:
@@ -632,7 +672,8 @@
       if (ospf_spf_has_vertex (rv, nv, w_lsa->data))
         {
           if (IS_DEBUG_OSPF_EVENT)
-            zlog_info ("The LSA is already in SPF");
+            zlog_info("The LSA for %s is already in SPF",
+		      inet_ntoa(w_lsa->data->id));
           continue;
         }
 
@@ -991,6 +1032,10 @@
          process). */
       node = listhead (candidate);
       v = getdata (node);
+      if (IS_DEBUG_OSPF_EVENT)
+	 zlog_info ("ospf_spf_calculate: processing candidate vertex %s",
+	            inet_ntoa(v->id));
+
       ospf_vertex_add_parent (v);
 
       /* Reveve from the candidate list. */
--- ./ospfd/ospf_interface.h.ptp	2004-02-11 16:52:13.000000000 -0500
+++ ./ospfd/ospf_interface.h	2004-04-26 13:57:01.000000000 -0400
@@ -213,6 +213,7 @@
 struct ospf_interface *ospf_if_addr_local (struct in_addr);
 struct ospf_interface *ospf_if_lookup_recv_if (struct ospf *, struct in_addr);
 struct ospf_interface *ospf_if_is_configured (struct ospf *, struct in_addr *);
+struct ospf_interface *ospf_if_is_connected (struct ospf *, struct in_addr *);
 
 struct ospf_if_params *ospf_lookup_if_params (struct interface *,
 					      struct in_addr);
--- ./ospfd/ospf_lsa.c.ptp	2003-10-13 05:06:46.000000000 -0400
+++ ./ospfd/ospf_lsa.c	2004-04-26 13:57:01.000000000 -0400
@@ -519,7 +519,8 @@
 	links++;
       }
 
-  if (oi->connected->destination != NULL)
+  if ((oi->connected->destination != NULL) &&
+      (oi->address->prefixlen == IPV4_MAX_PREFIXLEN))
     {
       /* Option 1:
 	 link_type = LSA_LINK_TYPE_STUB;
--- ./ospfd/ospf_packet.c.ptp	2004-04-04 08:52:33.000000000 -0400
+++ ./ospfd/ospf_packet.c	2004-04-26 13:57:01.000000000 -0400
@@ -647,8 +647,10 @@
       && oi->type != OSPF_IFTYPE_VIRTUALLINK)
     if (oi->address->prefixlen != p.prefixlen)
       {
-	zlog_warn ("Packet %s [Hello:RECV]: NetworkMask mismatch.",
-		   inet_ntoa (ospfh->router_id));
+	zlog_warn ("Packet %s [Hello:RECV]: NetworkMask mismatch: "
+		   "interface %s prefixlen %d vs. hello %d",
+		   inet_ntoa (ospfh->router_id),oi->ifp->name,
+		   oi->address->prefixlen,p.prefixlen);
 	return;
       }
 
--- ./ospfd/ospf_interface.c.ptp	2004-04-08 03:43:45.000000000 -0400
+++ ./ospfd/ospf_interface.c	2004-04-26 13:57:01.000000000 -0400
@@ -352,7 +352,9 @@
   for (node = listhead (ospf->oiflist); node; nextnode (node))
     if ((oi = getdata (node)) != NULL && oi->type != OSPF_IFTYPE_VIRTUALLINK)
       {
-	if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+	if ((oi->type == OSPF_IFTYPE_POINTOPOINT) &&
+	    oi->connected->destination &&
+	    (oi->address->prefixlen == IPV4_MAX_PREFIXLEN))
 	  addr = oi->connected->destination;
 	else
 	  addr = oi->address;
@@ -364,6 +366,48 @@
   return NULL;
 }
 
+/* similar to ospf_if_is_configured, but special treatment for PtP when
+   peer not specified or not using /32 addresses */
+struct ospf_interface *
+ospf_if_is_connected (struct ospf *ospf, struct in_addr *address)
+{
+  listnode node;
+  struct ospf_interface *oi;
+  struct prefix_ipv4 addr;
+
+  addr.family = AF_INET;
+  addr.prefix = *address;
+  addr.prefixlen = IPV4_MAX_PREFIXLEN;
+  
+  for (node = listhead (ospf->oiflist); node; nextnode (node))
+    if ((oi = getdata (node)) != NULL && oi->type != OSPF_IFTYPE_VIRTUALLINK)
+      {
+	if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+	  {
+	    if (oi->connected->destination &&
+		(oi->address->prefixlen == IPV4_MAX_PREFIXLEN))
+	      {
+		if (IPV4_ADDR_SAME (address,
+				    &oi->connected->destination->u.prefix4))
+		  return oi;
+	      }
+	    else
+	      {
+		/* special case: is the address somewhere on the PtP network? */
+		if (prefix_match(oi->address,(struct prefix *)&addr))
+		  return oi;
+	      }
+	  }
+	else
+	  {
+	    if (IPV4_ADDR_SAME (address, &oi->address->u.prefix4))
+	       return oi;
+	  }
+      }
+
+  return NULL;
+}
+
 int
 ospf_if_is_up (struct ospf_interface *oi)
 {
@@ -419,7 +463,8 @@
     {
       if ((oi = getdata (node)) != NULL && oi->type != OSPF_IFTYPE_VIRTUALLINK)
 	{
-	  if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+	  if ((oi->type == OSPF_IFTYPE_POINTOPOINT) &&
+	      oi->connected->destination)
 	    {
 	      prefix_copy (&ptmp, oi->connected->destination);
 	      ptmp.prefixlen = IPV4_MAX_BITLEN;
@@ -456,7 +501,7 @@
       if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
 	continue;
       
-      if (oi->type == OSPF_IFTYPE_POINTOPOINT)
+      if ((oi->type == OSPF_IFTYPE_POINTOPOINT) && oi->connected->destination)
 	{
 	  if (IPV4_ADDR_SAME (&oi->connected->destination->u.prefix4, &src))
 	    return oi;


More information about the Quagga-dev mailing list