On Tue, Jul 03, 2012 at 06:08:29PM +0200, Henning Brauer wrote:
> * Florian Obser <[email protected]> [2012-07-03 17:07]:
> > dammit, I turned this into the fix from hell :/
> > 
> > The patch tries to do the right thing when nh->true_nexthop.aid !=
> > nh->nexthop_net.aid I'm pretty sure this should never be the case for
> > AID_INET and AID_INET6 but no idea what AID_VPN_IPv4 does.
> > 
> > If nh->true_nexthop.aid != nh->nexthop_net.aid is *never* true the two
> > switch statements can be folded into one. 
> 
> we already have prefix_compare, let's use that. atm it requires the

Ah, nice, sorry for missing that.

> prefixlength to be passed in and to save us from the af-dependent max
> prefixlen figure out dance I changed prefix_compare to accept prefixlen
> -1 which in turn means maximum.
> 
> untested except for compilation.

FWIW it reads correct to me. Benno is going to give it a spin.

> 
> Index: rde_rib.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/rde_rib.c,v
> retrieving revision 1.133
> diff -u -p -r1.133 rde_rib.c
> --- rde_rib.c 1 Jul 2012 11:55:13 -0000       1.133
> +++ rde_rib.c 3 Jul 2012 16:06:32 -0000
> @@ -1056,8 +1056,10 @@ void
>  nexthop_update(struct kroute_nexthop *msg)
>  {
>       struct nexthop          *nh;
> +     struct bgpd_addr         oldtrue_nh, oldnh_net;
>       struct rde_aspath       *asp;
>       enum nexthop_state       oldstate;
> +     u_int8_t                 oldflags, oldnh_netlen;
>  
>       nh = nexthop_lookup(&msg->nexthop);
>       if (nh == NULL) {
> @@ -1067,6 +1069,11 @@ nexthop_update(struct kroute_nexthop *ms
>       }
>  
>       oldstate = nh->state;
> +     oldflags = nh->flags;
> +     oldnh_netlen = nh->nexthop_netlen;
> +     memcpy(&oldtrue_nh, &nh->true_nexthop, sizeof(oldtrue_nh));
> +     memcpy(&oldnh_net, &nh->nexthop_net, sizeof(oldnh_net));
> +
>       if (msg->valid)
>               nh->state = NEXTHOP_REACH;
>       else
> @@ -1087,6 +1094,15 @@ nexthop_update(struct kroute_nexthop *ms
>       if (nexthop_delete(nh))
>               /* nexthop no longer used */
>               return;
> +
> +     /* if there is no nexthop change, return early */
> +     if (oldstate == nh->state && oldflags == nh->flags &&
> +         oldnh_netlen == nh->nexthop_netlen &&
> +         oldnh_net.aid == nh->nexthop_net.aid) {
> +             if (prefix_compare(&oldtrue_nh, &nh->true_nexthop, -1) == 0 &&
> +                 prefix_compare(&oldnh_net, &nh->nexthop_net, -1) == 0)
> +                     return;
> +     }
>  
>       if (rde_noevaluate())
>               /*
> Index: util.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/bgpd/util.c,v
> retrieving revision 1.14
> diff -u -p -r1.14 util.c
> --- util.c    20 Sep 2011 21:19:07 -0000      1.14
> +++ util.c    3 Jul 2012 16:06:32 -0000
> @@ -422,16 +422,21 @@ prefix_compare(const struct bgpd_addr *a
>  
>       switch (a->aid) {
>       case AID_INET:
> -             if (prefixlen > 32)
> +             if (prefixlen < -1 || prefixlen > 32)
>                       fatalx("prefix_cmp: bad IPv4 prefixlen");
> -             mask = htonl(prefixlen2mask(prefixlen));
> +             if (prefixlen == -1)
> +                     mask = 0xffffffff;
> +             else
> +                     mask = htonl(prefixlen2mask(prefixlen));
>               aa = ntohl(a->v4.s_addr & mask);
>               ba = ntohl(b->v4.s_addr & mask);
>               if (aa != ba)
>                       return (aa - ba);
>               return (0);
>       case AID_INET6:
> -             if (prefixlen > 128)
> +             if (prefixlen == -1)
> +                     prefixlen = 128;
> +             else if (prefixlen > 128)
>                       fatalx("prefix_cmp: bad IPv6 prefixlen");
>               for (i = 0; i < prefixlen / 8; i++)
>                       if (a->v6.s6_addr[i] != b->v6.s6_addr[i])
> @@ -446,13 +451,16 @@ prefix_compare(const struct bgpd_addr *a
>               }
>               return (0);
>       case AID_VPN_IPv4:
> -             if (prefixlen > 32)
> -                     fatalx("prefix_cmp: bad IPv4 VPN prefixlen");
>               if (betoh64(a->vpn4.rd) > betoh64(b->vpn4.rd))
>                       return (1);
>               if (betoh64(a->vpn4.rd) < betoh64(b->vpn4.rd))
>                       return (-1);
> -             mask = htonl(prefixlen2mask(prefixlen));
> +             if (prefixlen < -1 || prefixlen > 32)
> +                     fatalx("prefix_cmp: bad IPv4 prefixlen");
> +             if (prefixlen == -1)
> +                     mask = 0xffffffff;
> +             else
> +                     mask = htonl(prefixlen2mask(prefixlen));
>               aa = ntohl(a->vpn4.addr.s_addr & mask);
>               ba = ntohl(b->vpn4.addr.s_addr & mask);
>               if (aa != ba)

Reply via email to