]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Interface logic changes:
authorMartin Mares <mj@ucw.cz>
Tue, 2 Mar 1999 17:28:06 +0000 (17:28 +0000)
committerMartin Mares <mj@ucw.cz>
Tue, 2 Mar 1999 17:28:06 +0000 (17:28 +0000)
o  Introduced IF_LINK_UP flag corresponding to real link state.
o  Allowed addressless interfaces.
o  IF_UP is now automatically calculated and set iff the interface
   is administratively up, has link up and has an IP address assigned.
   It may be IF_IGNORED, though (as in case of the loopback).
o  Any changes which include up/down transition are considered small
   enough to not provoke artificial upping and downing of the interface.
o  When an interface disappears (i.e., it wasn't seen in the last scan),
   we announce this change only once.
o  IF_LOOPBACK implies IF_IGNORE.

nest/iface.c
nest/iface.h
sysdep/unix/sync-if.c

index 86f0a8a1808c7c75c7338f914e36abeca545d68b..4d1b68566ce9cb2c97795d356915b9021928ea3b 100644 (file)
@@ -31,7 +31,7 @@ static list neigh_list;
 static int
 if_connected(ip_addr *a, struct iface *i) /* -1=error, 1=match, 0=no match */
 {
-  if (i->flags & (IF_ADMIN_DOWN | IF_IGNORE))
+  if (!(i->flags & IF_UP))
     return 0;
   if ((i->flags & IF_UNNUMBERED) && ipa_equal(*a, i->opposite))
     return 1;
@@ -41,8 +41,6 @@ if_connected(ip_addr *a, struct iface *i) /* -1=error, 1=match, 0=no match */
       ipa_equal(*a, i->brd) ||         /* Broadcast */
       ipa_equal(*a, i->ip))            /* Our own address */
     return -1;
-  if (!(i->flags & IF_UP))
-    return 0;
   return 1;
 }
 
@@ -197,6 +195,10 @@ if_dump(struct iface *i)
     debug(" ADMIN-DOWN");
   if (i->flags & IF_UP)
     debug(" UP");
+  else
+    debug(" DOWN");
+  if (i->flags & IF_LINK_UP)
+    debug(" LINK-UP");
   if (i->flags & IF_MULTIACCESS)
     debug(" MA");
   if (i->flags & IF_UNNUMBERED)
@@ -229,14 +231,16 @@ if_dump_all(void)
 static inline int
 if_change_too_big_p(struct iface *i, struct iface *j)
 {
-  if (!ipa_equal(i->ip, j->ip) ||
+  if ((i->flags ^ j->flags) & IF_UP)   /* Going up/down is always OK */
+    return 0;
+  if (!ipa_equal(i->ip, j->ip) ||      /* Address change isn't */
       !ipa_equal(i->prefix, j->prefix) ||
       i->pxlen != j->pxlen ||
       !ipa_equal(i->brd, j->brd) ||
       !ipa_equal(i->opposite, j->opposite))
-    return 1;                          /* Changed addresses */
-  if ((i->flags ^ j->flags) & ~(IF_UP | IF_ADMIN_DOWN | IF_UPDATED))
     return 1;
+  if ((i->flags ^ j->flags) & ~(IF_UP | IF_ADMIN_DOWN | IF_UPDATED | IF_LINK_UP))
+    return 1;                          /* Interface type change isn't as well */
   return 0;
 }
 
@@ -295,6 +299,11 @@ if_update(struct iface *new)
   struct iface *i;
   unsigned c;
 
+  if ((new->flags & IF_LINK_UP) && !(new->flags & IF_ADMIN_DOWN) && ipa_nonzero(new->ip))
+    new->flags |= IF_UP;
+  else
+    new->flags &= ~IF_UP;
+
   WALK_LIST(i, iface_list)
     if (!strcmp(new->name, i->name))
       {
@@ -337,8 +346,9 @@ if_end_update(void)
     else
       {
        memcpy(&j, i, sizeof(struct iface));
-       i->flags = (i->flags & ~IF_UP) | IF_ADMIN_DOWN;
-       if_notify_change(IF_CHANGE_DOWN | IF_CHANGE_FLAGS, &j, i);
+       i->flags = (i->flags & ~(IF_LINK_UP | IF_UP)) | IF_ADMIN_DOWN;
+       if (i->flags != j.flags)
+         if_notify_change(IF_CHANGE_DOWN | IF_CHANGE_FLAGS, &j, i);
       }
 }
 
@@ -362,7 +372,7 @@ auto_router_id(void)                        /* FIXME: What if we run IPv6??? */
   j = NULL;
   WALK_LIST(i, iface_list)
     if ((i->flags & IF_UP) &&
-       !(i->flags & (IF_UNNUMBERED | IF_LOOPBACK | IF_IGNORE)) &&
+       !(i->flags & (IF_UNNUMBERED | IF_IGNORE)) &&
        (!j || ipa_to_u32(i->ip) < ipa_to_u32(j->ip)))
       j = i;
   if (!j)
index 378cf3d15616364dbb13c5e3e234c3b69f8a8c79..fcad71879b9a23f02e6f3ad796050f533599ecee 100644 (file)
@@ -21,7 +21,7 @@ struct iface {
   unsigned flags;
   unsigned mtu;
   unsigned index;                      /* OS-dependent interface index */
-  ip_addr ip;                          /* IP address of this host */
+  ip_addr ip;                          /* IP address of this host (0=unset) */
   ip_addr prefix;                      /* Network prefix */
   unsigned pxlen;                      /* Prefix length */
   ip_addr brd;                         /* Broadcast address */
@@ -29,7 +29,7 @@ struct iface {
   struct neighbor *neigh;              /* List of neighbors on this interface */
 };
 
-#define IF_UP 1
+#define IF_UP 1                                /* IF_LINK_UP, not IF_IGNORE and IP address known */
 #define IF_MULTIACCESS 2
 #define IF_UNNUMBERED 4
 #define IF_BROADCAST 8
@@ -38,7 +38,8 @@ struct iface {
 #define IF_ADMIN_DOWN 64
 #define IF_LOOPBACK 128
 #define IF_IGNORE 256
-#define IF_UPDATED 0x1000              /* Touched in last scan */
+#define IF_LINK_UP 512
+#define IF_UPDATED 0x40000000          /* Touched in last scan */
 
 /* Interface change events */
 
index 077cb94a7350f88aaa53b01cce440eb7380177fc..ce54fc77d0d4b2145a79d042d9bb10a9e7cb8b94 100644 (file)
@@ -42,16 +42,18 @@ scan_ifs(struct ifreq *r, int cnt)
       bzero(&i, sizeof(i));
       DBG("%s\n", r->ifr_ifrn.ifrn_name);
       strncpy(i.name, r->ifr_ifrn.ifrn_name, sizeof(i.name) - 1);
-      i.name[sizeof(i.name) - 1] = 0;
       get_sockaddr((struct sockaddr_in *) &r->ifr_addr, &i.ip, NULL);
-      l = ipa_classify(i.ip);
-      if (l < 0 || !(l & IADDR_HOST))
+      if (ipa_nonzero(i.ip))
        {
-         log(L_ERR "%s: Invalid interface address", i.name);
-         goto bad;
+         l = ipa_classify(i.ip);
+         if (l < 0 || !(l & IADDR_HOST))
+           {
+             log(L_ERR "%s: Invalid interface address", i.name);
+             i.ip = IPA_NONE;
+           }
+         else if ((l & IADDR_SCOPE_MASK) == SCOPE_HOST)
+           i.flags |= IF_LOOPBACK | IF_IGNORE;
        }
-      if ((l & IADDR_SCOPE_MASK) == SCOPE_HOST)
-       i.flags |= IF_LOOPBACK | IF_IGNORE;
 
       if (ioctl(if_scan_sock, SIOCGIFFLAGS, r) < 0)
        {
@@ -59,12 +61,12 @@ scan_ifs(struct ifreq *r, int cnt)
        faulty:
          log(L_ERR "%s(%s): %m", err, i.name);
        bad:
-         i.flags = (i.flags & ~IF_UP) | IF_ADMIN_DOWN;
+         i.flags = (i.flags & ~IF_LINK_UP) | IF_ADMIN_DOWN;
          continue;
        }
       fl = r->ifr_flags;
       if (fl & IFF_UP)
-       i.flags |= IF_UP;
+       i.flags |= IF_LINK_UP;
 
       if (ioctl(if_scan_sock, SIOCGIFNETMASK, r) < 0)
        { err = "SIOCGIFNETMASK"; goto faulty; }
@@ -120,6 +122,8 @@ scan_ifs(struct ifreq *r, int cnt)
        DBG("SIOCGIFINDEX failed: %m\n");
       else
        i.index = r->ifr_ifindex;
+#else
+      /* FIXME: What else? Guess ifindex (we need it at least for OSPF on unnumbered links)? */
 #endif
 
       if_update(&i);