funny ECMP

Ingo Flaschberger if at xip.at
Wed Aug 25 22:52:48 UTC 2010


Hi,

currently I stick at this (last?) problem:

assume routingtable:		net			gw
postion		type
1		route		10.13.13.0/24		10.11.11.1
2		route		10.13.13.0/24		10.11.11.2
3		interface route 10.13.13.90/24

delete route 2
delete route 1
-> ping 10.13.13.95 via interface -> crash

because route 2 is not deleted from radix_mask-list,
route 2 appears again, but is deleted - kernel panic


Problem is generated here:
sys/net/radix.c in rn_addroute
         /* Promote general routes from below */
         if (x->rn_bit < 0) {
            printf("rn_addroute: x->rn_bit < 0\n");
             for (mp = &t->rn_mklist; x; x = x->rn_dupedkey) {
                 printf("rn_addroute: for (mp = &t->rn_mklist; x; x = x->rn_dupedkey)\n");
                 /* XXX what todo with multipath-routes?? */
here for every multipath-route
of this netmask a new radix-mask
is added when the route for an interface
is added.
I'm not shure if the generated mask are linked together?
(Should they be linked?)

                 if (x->rn_mask && (x->rn_bit >= b_leaf) && x->rn_mklist == 0) {
                         printf("rn_addroute: new mask - next = 0\n");
                         *mp = m = rn_new_radix_mask(x, 0);
                         if (m) {
                                 mp = &m->rm_mklist;
                                 printf("rn_addroute: if (m)\n");
                         }
                 }
             }

Final crash occurs in route.c after getting a rt_entry back from here:
sys/net/radix.c in rn_match
         /* start searching up the tree */
         do {
                 register struct radix_mask *m;
                 t = t->rn_parent;
                 printf("rn_match: parent %lu\n", (u_int64_t) t);
                 m = t->rn_mklist;
                 /*
                  * If non-contiguous masks ever become important
                  * we can restore the masking and open coding of
                  * the search and satisfaction test and put the
                  * calculation of "off" back before the "do".
                  */
                 while (m) {
                         if (m->rm_flags & RNF_NORMAL) {
                                 if (rn_bit <= m->rm_bit) {
                                         printf("rn_match: found leaf: %lu\n", (u_int64_t) m->rm_leaf);
The already deleted route 2 is then
found again!
                                         return (m->rm_leaf);
                                 }
                         } else {
                                 off = min(t->rn_offset, matched_off);
                                 x = rn_search_m(v, t, m->rm_mask);
                                 while (x && x->rn_mask != m->rm_mask)
                                         x = x->rn_dupedkey;
                                 if (x && rn_satisfies_leaf(v, x, off)) {
                                         printf("rn_match: rn_satisfies_leaf: %lu\n", (u_int64_t) x);
                                         return x;
                                 }
                         }
                         m = m->rm_mklist;
                 }
         } while (t != top);

The problem happen only for more than 2 same route sin the system.
sys/net/radix_mpath.c in rt_mpath_deldup
the radix_masklist should be deleted, changed?
rt_mpath_deldup is only called for the 2nd and more routes in the table,
the first route is deleted with standard radix delete.


I have really no idea how radix_mask (should) work - help really needed.

Kind regards,
 	Ingo Flaschberger


More information about the freebsd-net mailing list