Hi,

in some circumstances ospfd behaves not the way a user would expect and
it's not easy understand how to recover. With below diff ospfd recovers
automatically from the following three cases.

1) netstart

When someone runs the netstart script on a running system it most likely
assigns the already configured addresses. This leads first to a removal
of the address and then it is added again. ospfd now lost it's multicast
group but is not able to re-join.

To recover ospfd these steps are needed (without the diff):
- remove interface from ospfd.conf
- ospfctl reload
- add interface to ospfd.conf
- ospfctl reload

2) netmask change

When the netmask changes but the IP address stays the same a reload is
needed. Otherwise the adjacency will not come up again on the interface
with the changed config.

I think this is not obvious for a user since the config file needs no change.

3) dest address change

When the dest address on a point-to-point interface is changed but the local
address stays the same recovery procedure is needed as for 1). But
ospfd.conf does not change.


While working on this I thought that it would be nice to use the ifindex
for joining and leaving multicast groups via setsockopts instead of the IP.
But I can not judge if it would be useful in other cases.

In addition it would be nice if the kernel would do nothing if the new
address and mask is the sam as the existing one.

This is my 2nd attempt. See this thread for the previous one with discussion:
https://marc.info/?t=149842729800001&r=1&w=2


OK?

Remi

Index: kroute.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospfd/kroute.c,v
retrieving revision 1.109
diff -u -p -r1.109 kroute.c
--- kroute.c    11 Feb 2018 02:27:33 -0000      1.109
+++ kroute.c    12 Jun 2018 20:41:43 -0000
@@ -1074,6 +1074,7 @@ if_newaddr(u_short ifindex, struct socka
 {
        struct kif_node *kif;
        struct kif_addr *ka;
+       struct ifaddr    ifn;
 
        if (ifa == NULL || ifa->sin_family != AF_INET)
                return;
@@ -1094,6 +1095,12 @@ if_newaddr(u_short ifindex, struct socka
                ka->dstbrd.s_addr = INADDR_NONE;
 
        TAILQ_INSERT_TAIL(&kif->addrs, ka, entry);
+
+       ifn.addr = ka->addr;
+       ifn.mask = ka->mask;
+       ifn.dst = ka->dstbrd;
+       ifn.ifindex = ifindex;
+       main_imsg_compose_ospfe(IMSG_IFADDRADD, 0, &ifn, sizeof(ifn));
 }
 
 void
@@ -1102,7 +1109,7 @@ if_deladdr(u_short ifindex, struct socka
 {
        struct kif_node *kif;
        struct kif_addr *ka, *nka;
-       struct ifaddrdel ifc;
+       struct ifaddr    ifc;
 
        if (ifa == NULL || ifa->sin_family != AF_INET)
                return;
Index: ospfd.h
===================================================================
RCS file: /cvs/src/usr.sbin/ospfd/ospfd.h,v
retrieving revision 1.100
diff -u -p -r1.100 ospfd.h
--- ospfd.h     11 Feb 2018 02:27:33 -0000      1.100
+++ ospfd.h     12 Jun 2018 20:41:43 -0000
@@ -132,6 +132,7 @@ enum imsg_type {
        IMSG_RECONF_REDIST,
        IMSG_RECONF_END,
        IMSG_DEMOTE,
+       IMSG_IFADDRADD,
        IMSG_IFADDRDEL
 };
 
@@ -363,8 +364,10 @@ struct iface {
        u_int8_t                 passive;
 };
 
-struct ifaddrdel {
+struct ifaddr {
        struct in_addr          addr;
+       struct in_addr          mask;
+       struct in_addr          dst;
        unsigned int            ifindex;
 };
 
Index: ospfe.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospfd/ospfe.c,v
retrieving revision 1.100
diff -u -p -r1.100 ospfe.c
--- ospfe.c     5 Feb 2018 12:11:28 -0000       1.100
+++ ospfe.c     18 Jun 2018 05:56:16 -0000
@@ -275,7 +275,7 @@ ospfe_dispatch_main(int fd, short event,
 {
        static struct area      *narea;
        static struct iface     *niface;
-       struct ifaddrdel        *ifc;
+       struct ifaddr   *ifc;
        struct imsg      imsg;
        struct imsgev   *iev = bula;
        struct imsgbuf  *ibuf = &iev->ibuf;
@@ -361,9 +361,38 @@ ospfe_dispatch_main(int fd, short event,
                                }
                        }
                        break;
+               case IMSG_IFADDRADD:
+                       if (imsg.hdr.len != IMSG_HEADER_SIZE +
+                           sizeof(struct ifaddr))
+                               fatalx("IFADDRADD imsg with wrong len");
+                       ifc = imsg.data;
+
+                       LIST_FOREACH(area, &oeconf->area_list, entry) {
+                               LIST_FOREACH(iface, &area->iface_list, entry) {
+                                       if (ifc->ifindex == iface->ifindex &&
+                                           ifc->addr.s_addr ==
+                                           iface->addr.s_addr) {
+                                               iface->mask = ifc->mask;
+                                               iface->dst = ifc->dst;
+                                               /*
+                                                * Previous down event might
+                                                * have failed if the address
+                                                * was not present at that
+                                                * time.
+                                                */
+                                               if_fsm(iface, IF_EVT_DOWN);
+                                               if_fsm(iface, IF_EVT_UP);
+                                               log_warnx("interface %s:%s "
+                                                   "returned", iface->name,
+                                                   inet_ntoa(iface->addr));
+                                               break;
+                                       }
+                               }
+                       }
+                       break;
                case IMSG_IFADDRDEL:
                        if (imsg.hdr.len != IMSG_HEADER_SIZE +
-                           sizeof(struct ifaddrdel))
+                           sizeof(struct ifaddr))
                                fatalx("IFADDRDEL imsg with wrong len");
                        ifc = imsg.data;
 

Reply via email to