This is another cleanup round of the route decision process. This time focusing on prefix_cmp(). Make sure that when using return (a - b) that the results always fits in an int type. Also make sure the check of the remote_addr at the end is done properly. The result is probably the same but this is the same way it is done in many other places.
Unless I made a mistake the result should still be the same. -- :wq Claudio ? obj Index: rde_decide.c =================================================================== RCS file: /cvs/src/usr.sbin/bgpd/rde_decide.c,v retrieving revision 1.79 diff -u -p -r1.79 rde_decide.c --- rde_decide.c 13 Jan 2021 11:34:01 -0000 1.79 +++ rde_decide.c 13 Jan 2021 12:08:21 -0000 @@ -113,12 +113,12 @@ prefix_cmp(struct prefix *p1, struct pre struct rde_peer *peer1, *peer2; struct attr *a; u_int32_t p1id, p2id; - int p1cnt, p2cnt; + int p1cnt, p2cnt, i; if (p1 == NULL) - return (-1); + return -1; if (p2 == NULL) - return (1); + return 1; asp1 = prefix_aspath(p1); asp2 = prefix_aspath(p2); @@ -127,15 +127,15 @@ prefix_cmp(struct prefix *p1, struct pre /* pathes with errors are not eligible */ if (asp1 == NULL || asp1->flags & F_ATTR_PARSE_ERR) - return (-1); + return -1; if (asp2 == NULL || asp2->flags & F_ATTR_PARSE_ERR) - return (1); + return 1; /* only loop free pathes are eligible */ if (asp1->flags & F_ATTR_LOOP) - return (-1); + return -1; if (asp2->flags & F_ATTR_LOOP) - return (1); + return 1; /* * 1. check if prefix is eligible a.k.a reachable @@ -144,14 +144,16 @@ prefix_cmp(struct prefix *p1, struct pre */ if (prefix_nexthop(p2) != NULL && prefix_nexthop(p2)->state != NEXTHOP_REACH) - return (1); + return 1; if (prefix_nexthop(p1) != NULL && prefix_nexthop(p1)->state != NEXTHOP_REACH) - return (-1); + return -1; /* 2. local preference of prefix, bigger is better */ - if ((asp1->lpref - asp2->lpref) != 0) - return (asp1->lpref - asp2->lpref); + if (asp1->lpref > asp2->lpref) + return 1; + if (asp1->lpref < asp2->lpref) + return -1; /* 3. aspath count, the shorter the better */ if ((asp2->aspath->ascnt - asp1->aspath->ascnt) != 0) @@ -161,12 +163,19 @@ prefix_cmp(struct prefix *p1, struct pre if ((asp2->origin - asp1->origin) != 0) return (asp2->origin - asp1->origin); - /* 5. MED decision, only comparable between the same neighboring AS */ - if (rde_decisionflags() & BGPD_FLAG_DECISION_MED_ALWAYS || - aspath_neighbor(asp1->aspath) == aspath_neighbor(asp2->aspath)) + /* + * 5. MED decision + * Only comparable between the same neighboring AS or if + * 'rde med compare always' is set. + */ + if ((rde_decisionflags() & BGPD_FLAG_DECISION_MED_ALWAYS) || + aspath_neighbor(asp1->aspath) == aspath_neighbor(asp2->aspath)) { /* lowest value wins */ - if ((asp2->med - asp1->med) != 0) - return (asp2->med - asp1->med); + if (asp1->med < asp2->med) + return 1; + if (asp1->med > asp2->med) + return -1; + } /* * 6. EBGP is cooler than IBGP @@ -187,8 +196,10 @@ prefix_cmp(struct prefix *p1, struct pre * a metric that weights a prefix at a very late stage in the * decision process. */ - if ((asp1->weight - asp2->weight) != 0) - return (asp1->weight - asp2->weight); + if (asp1->weight > asp2->weight) + return 1; + if (asp1->weight < asp2->weight) + return -1; /* 8. nexthop costs. NOT YET -> IGNORE */ @@ -196,9 +207,12 @@ prefix_cmp(struct prefix *p1, struct pre * 9. older route (more stable) wins but only if route-age * evaluation is enabled. */ - if (rde_decisionflags() & BGPD_FLAG_DECISION_ROUTEAGE) - if ((p2->lastchange - p1->lastchange) != 0) - return (p2->lastchange - p1->lastchange); + if (rde_decisionflags() & BGPD_FLAG_DECISION_ROUTEAGE) { + if (p1->lastchange < p2->lastchange) /* p1 is older */ + return 1; + if (p1->lastchange > p2->lastchange) + return -1; + } /* 10. lowest BGP Id wins, use ORIGINATOR_ID if present */ if ((a = attr_optget(asp1, ATTR_ORIGINATOR_ID)) != NULL) { @@ -211,8 +225,10 @@ prefix_cmp(struct prefix *p1, struct pre p2id = ntohl(p2id); } else p2id = peer2->remote_bgpid; - if ((p2id - p1id) != 0) - return (p2id - p1id); + if (p1id < p2id) + return 1; + if (p1id > p2id) + return -1; /* 11. compare CLUSTER_LIST length, shorter is better */ p1cnt = p2cnt = 0; @@ -224,10 +240,26 @@ prefix_cmp(struct prefix *p1, struct pre return (p2cnt - p1cnt); /* 12. lowest peer address wins (IPv4 is better than IPv6) */ - if (memcmp(&peer1->remote_addr, &peer2->remote_addr, - sizeof(peer1->remote_addr)) != 0) - return (-memcmp(&peer1->remote_addr, &peer2->remote_addr, - sizeof(peer1->remote_addr))); + if (peer1->remote_addr.aid < peer2->remote_addr.aid) + return 1; + if (peer1->remote_addr.aid > peer2->remote_addr.aid) + return -1; + switch (peer1->remote_addr.aid) { + case AID_INET: + i = memcmp(&peer1->remote_addr.v4, &peer2->remote_addr.v4, + sizeof(struct in_addr)); + break; + case AID_INET6: + i = memcmp(&peer1->remote_addr.v6, &peer2->remote_addr.v6, + sizeof(struct in6_addr)); + break; + default: + fatalx("%s: unknown af", __func__); + } + if (i < 0) + return 1; + if (i > 0) + return -1; fatalx("Uh, oh a politician in the decision process"); }