Diff for /embedaddon/quagga/zebra/connected.c between versions 1.1.1.3 and 1.1.1.4

version 1.1.1.3, 2013/07/21 23:54:41 version 1.1.1.4, 2016/11/02 10:09:10
Line 36 Line 36
 #include "zebra/interface.h"  #include "zebra/interface.h"
 #include "zebra/connected.h"  #include "zebra/connected.h"
 extern struct zebra_t zebrad;  extern struct zebra_t zebrad;
/* withdraw a connected address *//* communicate the withdrawal of a connected address */
 static void  static void
 connected_withdraw (struct connected *ifc)  connected_withdraw (struct connected *ifc)
 {  {
Line 49  connected_withdraw (struct connected *ifc) Line 49  connected_withdraw (struct connected *ifc)
     {      {
       zebra_interface_address_delete_update (ifc->ifp, ifc);        zebra_interface_address_delete_update (ifc->ifp, ifc);
   
       if_subnet_delete (ifc->ifp, ifc);  
         
       if (ifc->address->family == AF_INET)        if (ifc->address->family == AF_INET)
           if_subnet_delete (ifc->ifp, ifc);
   
         if (ifc->address->family == AF_INET)
         connected_down_ipv4 (ifc->ifp, ifc);          connected_down_ipv4 (ifc->ifp, ifc);
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
       else        else
Line 61  connected_withdraw (struct connected *ifc) Line 62  connected_withdraw (struct connected *ifc)
       UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);        UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL);
     }      }
   
     /* The address is not in the kernel anymore, so clear the flag */
     UNSET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
   
   if (!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))    if (!CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED))
     {      {
       listnode_delete (ifc->ifp->connected, ifc);        listnode_delete (ifc->ifp->connected, ifc);
Line 77  connected_announce (struct interface *ifp, struct conn Line 81  connected_announce (struct interface *ifp, struct conn
   listnode_add (ifp->connected, ifc);    listnode_add (ifp->connected, ifc);
   
   /* Update interface address information to protocol daemon. */    /* Update interface address information to protocol daemon. */
  if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL))  if (ifc->address->family == AF_INET)
    {    if_subnet_add (ifp, ifc);
      if (ifc->address->family == AF_INET) 
        if_subnet_add (ifp, ifc); 
   
      SET_FLAG (ifc->conf, ZEBRA_IFC_REAL);  zebra_interface_address_add_update (ifp, ifc);
   
      zebra_interface_address_add_update (ifp, ifc);  if (if_is_operative(ifp))
    {
      if (if_is_operative(ifp))      if (ifc->address->family == AF_INET)
        {        connected_up_ipv4 (ifp, ifc);
          if (ifc->address->family == AF_INET) 
            connected_up_ipv4 (ifp, ifc); 
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
          else      else
            connected_up_ipv6 (ifp, ifc);        connected_up_ipv6 (ifp, ifc);
 #endif  #endif
         }  
     }      }
 }  }
 /* If same interface address is already exist... */  /* If same interface address is already exist... */
 struct connected *  struct connected *
 connected_check (struct interface *ifp, struct prefix *p)  connected_check (struct interface *ifp, struct prefix *p)
Line 112  connected_check (struct interface *ifp, struct prefix  Line 111  connected_check (struct interface *ifp, struct prefix 
   return NULL;    return NULL;
 }  }
   
/* Check if two ifc's describe the same address *//* Check if two ifc's describe the same address in the same state */
 static int  static int
 connected_same (struct connected *ifc1, struct connected *ifc2)  connected_same (struct connected *ifc1, struct connected *ifc2)
 {  {
Line 132  connected_same (struct connected *ifc1, struct connect Line 131  connected_same (struct connected *ifc1, struct connect
   
   if (ifc1->flags != ifc2->flags)    if (ifc1->flags != ifc2->flags)
     return 0;      return 0;
   
     if (ifc1->conf != ifc2->conf)
       return 0;
       
   return 1;    return 1;
 }  }
   
/* Handle implicit withdrawals of addresses, where a system ADDs an address/* Handle changes to addresses and send the neccesary announcements
 * to an interface which already has the same address configured. * to clients. */
 *static void
 * Returns the struct connected which must be announced to clients,connected_update(struct interface *ifp, struct connected *ifc)
 * or NULL if nothing to do. 
 */ 
static struct connected * 
connected_implicit_withdraw (struct interface *ifp, struct connected *ifc) 
 {  {
   struct connected *current;    struct connected *current;
       
Line 156  connected_implicit_withdraw (struct interface *ifp, st Line 154  connected_implicit_withdraw (struct interface *ifp, st
       /* Avoid spurious withdraws, this might be just the kernel 'reflecting'        /* Avoid spurious withdraws, this might be just the kernel 'reflecting'
        * back an address we have already added.         * back an address we have already added.
        */         */
      if (connected_same (current, ifc) && CHECK_FLAG(current->conf, ZEBRA_IFC_REAL))      if (connected_same (current, ifc))
         {          {
           /* nothing to do */            /* nothing to do */
           connected_free (ifc);            connected_free (ifc);
          return NULL;          return;
         }          }
      
       /* Clear the configured flag on the old ifc, so it will be freed by
        * connected withdraw. */
       UNSET_FLAG(current->conf, ZEBRA_IFC_CONFIGURED);        UNSET_FLAG(current->conf, ZEBRA_IFC_CONFIGURED);
       connected_withdraw (current); /* implicit withdraw - freebsd does this */        connected_withdraw (current); /* implicit withdraw - freebsd does this */
     }      }
  return ifc;
   /* If the connected is new or has changed, announce it, if it is usable */
   if (CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
     connected_announce(ifp, ifc);
 }  }
   
 /* Called from if_up(). */  /* Called from if_up(). */
Line 189  connected_up_ipv4 (struct interface *ifp, struct conne Line 192  connected_up_ipv4 (struct interface *ifp, struct conne
     return;      return;
   
   rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,    rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,
        RT_TABLE_MAIN, ifp->metric, 0, SAFI_UNICAST);       ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_UNICAST);
   
   rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,    rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, NULL, ifp->ifindex,
        RT_TABLE_MAIN, ifp->metric, 0, SAFI_MULTICAST);       ifp->vrf_id, RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_MULTICAST);
   
  rib_update ();  rib_update (ifp->vrf_id);
 }  }
   
 /* Add connected IPv4 route to the interface. */  /* Add connected IPv4 route to the interface. */
Line 210  connected_add_ipv4 (struct interface *ifp, int flags,  Line 213  connected_add_ipv4 (struct interface *ifp, int flags, 
   ifc = connected_new ();    ifc = connected_new ();
   ifc->ifp = ifp;    ifc->ifp = ifp;
   ifc->flags = flags;    ifc->flags = flags;
     /* If we get a notification from the kernel,
      * we can safely assume the address is known to the kernel */
     SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
   
   /* Allocate new connected address. */    /* Allocate new connected address. */
   p = prefix_ipv4_new ();    p = prefix_ipv4_new ();
Line 272  connected_add_ipv4 (struct interface *ifp, int flags,  Line 278  connected_add_ipv4 (struct interface *ifp, int flags, 
   if (label)    if (label)
     ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);      ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
   
  /* nothing to do? */  /* For all that I know an IPv4 address is always ready when we receive
  if ((ifc = connected_implicit_withdraw (ifp, ifc)) == NULL)   * the notification. So it should be safe to set the REAL flag here. */
    return;  SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
  
  connected_announce (ifp, ifc);  connected_update(ifp, ifc);
 }  }
   
 void  void
Line 298  connected_down_ipv4 (struct interface *ifp, struct con Line 304  connected_down_ipv4 (struct interface *ifp, struct con
     return;      return;
   
   /* Same logic as for connected_up_ipv4(): push the changes into the head. */    /* Same logic as for connected_up_ipv4(): push the changes into the head. */
  rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_UNICAST);  rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, ifp->vrf_id,
                    SAFI_UNICAST);
   
  rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_MULTICAST);  rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, ifp->vrf_id,
                    SAFI_MULTICAST);
   
  rib_update ();  rib_update (ifp->vrf_id);
 }  }
   
 /* Delete connected IPv4 route to the interface. */  /* Delete connected IPv4 route to the interface. */
Line 324  connected_delete_ipv4 (struct interface *ifp, int flag Line 332  connected_delete_ipv4 (struct interface *ifp, int flag
           
   connected_withdraw (ifc);    connected_withdraw (ifc);
   
  rib_update();  rib_update (ifp->vrf_id);
 }  }
   
 #ifdef HAVE_IPV6  #ifdef HAVE_IPV6
Line 341  connected_up_ipv6 (struct interface *ifp, struct conne Line 349  connected_up_ipv6 (struct interface *ifp, struct conne
   /* Apply mask to the network. */    /* Apply mask to the network. */
   apply_mask_ipv6 (&p);    apply_mask_ipv6 (&p);
   
#if ! defined (MUSICA) && ! defined (LINUX)#ifndef LINUX
   /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */    /* XXX: It is already done by rib_bogus_ipv6 within rib_add_ipv6 */
   if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))    if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
     return;      return;
 #endif  #endif
   
  rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, RT_TABLE_MAIN,  rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, ifp->vrf_id,
                ifp->metric, 0, SAFI_UNICAST);                RT_TABLE_MAIN, ifp->metric, 0, 0, SAFI_UNICAST);
   
  rib_update ();  rib_update (ifp->vrf_id);
 }  }
   
 /* Add connected IPv6 route to the interface. */  /* Add connected IPv6 route to the interface. */
Line 366  connected_add_ipv6 (struct interface *ifp, int flags,  Line 374  connected_add_ipv6 (struct interface *ifp, int flags, 
   ifc = connected_new ();    ifc = connected_new ();
   ifc->ifp = ifp;    ifc->ifp = ifp;
   ifc->flags = flags;    ifc->flags = flags;
     /* If we get a notification from the kernel,
      * we can safely assume the address is known to the kernel */
     SET_FLAG(ifc->conf, ZEBRA_IFC_QUEUED);
   
   /* Allocate new connected address. */    /* Allocate new connected address. */
   p = prefix_ipv6_new ();    p = prefix_ipv6_new ();
Line 400  connected_add_ipv6 (struct interface *ifp, int flags,  Line 411  connected_add_ipv6 (struct interface *ifp, int flags, 
   /* Label of this address. */    /* Label of this address. */
   if (label)    if (label)
     ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);      ifc->label = XSTRDUP (MTYPE_CONNECTED_LABEL, label);
  
  if ((ifc = connected_implicit_withdraw (ifp, ifc)) == NULL)  /* On Linux, we only get here when DAD is complete, therefore we can set
    return;   * ZEBRA_IFC_REAL.
     *
  connected_announce (ifp, ifc);   * On BSD, there currently doesn't seem to be a way to check for completion of
    * DAD, so we replicate the old behaviour and set ZEBRA_IFC_REAL, although DAD
    * might still be running.
    */
   SET_FLAG(ifc->conf, ZEBRA_IFC_REAL);
   connected_update(ifp, ifc);
 }  }
   
 void  void
Line 422  connected_down_ipv6 (struct interface *ifp, struct con Line 438  connected_down_ipv6 (struct interface *ifp, struct con
   if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))    if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix))
     return;      return;
   
  rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, SAFI_UNICAST);  rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, ifp->vrf_id,
                    SAFI_UNICAST);
   
  rib_update ();  rib_update (ifp->vrf_id);
 }  }
   
 void  void
Line 445  connected_delete_ipv6 (struct interface *ifp, struct i Line 462  connected_delete_ipv6 (struct interface *ifp, struct i
   
   connected_withdraw (ifc);    connected_withdraw (ifc);
   
  rib_update();  rib_update (ifp->vrf_id);
 }  }
 #endif /* HAVE_IPV6 */  #endif /* HAVE_IPV6 */

Removed from v.1.1.1.3  
changed lines
  Added in v.1.1.1.4


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>