Here's the patch for making the RTF_UP show up properly when changing
a gateway from/to an up/down link.

--- /usr/src/sys/net/rtsock.c   Tue Dec  1 00:36:58 2009
+++ rtsock.c    Mon Dec  7 23:36:20 2009
@@ -641,6 +641,19 @@ report:
                                }
                        }

+                       /* new gateway, possible link state change  */
+                       if ((LINK_STATE_IS_UP(ifa->ifa_ifp->if_link_state) ||
+                               ifa->ifa_ifp->if_link_state ==
LINK_STATE_UNKNOWN) &&
+                               ifa->ifa_ifp->if_flags & IFF_UP) {
+                                       rt->rt_flags |= RTF_UP;
+                                       rt->rt_priority &= RTP_MASK;
+                       }
+                       else {
+                               rt->rt_flags &= ~RTF_UP;
+                               rtm->rtm_flags &= RTF_UP;
+                               rt->rt_priority |= RTP_DOWN;
+                       }
+
                        /* XXX Hack to allow some flags to be toggled */
                        if (rtm->rtm_fmask & RTF_FMASK)
                                rt->rt_flags = (rt->rt_flags &

The above patch made apparent that the RTP_DOWN flag needed to be
taken into handled properly in rt_mpath_conflict.

--- /usr/src/sys/net/radix_mpath.c      Mon Apr 20 17:01:35 2009
+++ radix_mpath.c       Tue Dec  8 01:16:21 2009
@@ -282,6 +282,7 @@ rt_mpath_conflict(struct radix_node_head *rnh, struct
        struct rtentry *rt1;
        char *p, *q, *eq;
        int same, l, skip;
+       u_int8_t prio;

        rn = (struct radix_node *)rt;
        rn1 = rnh->rnh_lookup(rt_key(rt), netmask, rnh);
@@ -348,10 +349,13 @@ rt_mpath_conflict(struct radix_node_head *rnh, struct
        }

  maskmatched:
-       if (!mpathok && rt1->rt_priority == rt->rt_priority)
+       /* consider route even if RTP_DOWN */
+       prio = rt->rt_priority & RTP_MASK;
+
+       if (!mpathok && (prio == (rt->rt_priority & RTP_MASK)))
                return EEXIST;

-       rn1 = rn_mpath_prio((struct radix_node *)rt1, rt->rt_priority);
+       rn1 = rn_mpath_prio((struct radix_node *)rt1, prio);
        /* key/mask were the same.  compare gateway for all multipaths */
        do {
                rt1 = (struct rtentry *)rn1;
@@ -366,12 +370,12 @@ rt_mpath_conflict(struct radix_node_head *rnh, struct
                        continue;

                /* check the route priority */
-               if (rt1->rt_priority != rt->rt_priority)
+               if ((rt1->rt_priority & RTP_MASK) != prio)
                        continue;

                /* all key/mask/gateway are the same.  conflicting entry. */
                return EEXIST;
-       } while ((rn1 = rn_mpath_next(rn1, 0)) != NULL);
+       } while ((rn1 = rn_mpath_next(rn1, 1)) != NULL);

  different:
        return 0;

Finally when adding or deleting multipath routes that could be flagged
as RTP_DOWN need to be handled also. I haven't gotten to writing a
patch for that yet.

dmo

Reply via email to