On Wed, Apr 14, 2021 at 11:56:08PM +0200, Alexander Bluhm wrote:
> Hi,
>
> On powerpc64 regress/usr.sbin/bgpd/config fails. It parses a config
> file, writes bgpd's config to stdout and compares it with an expected
> output.
>
> On powerpc64 the order of the set of communities is different.
>
> The parser uses memcmp(3) to sort a struct of integers. This depends
> of the endianess. The correct way is to compare the integer fields
> in native byte order.
>
> With this diff, the resulting order is the same on i386 and poerpc64.
> Also on powerpc64 the fix does not change bgpd's output. memcmp(3)
> and field comparison are equivalent on big endian architectures.
>
> ok?
OK claudio@
There are more places where communities are memcmp (filterset_cmp(),
filterset_equal()) but in these cases only equality matters.
filterset_add() needs to ensure that equal filterset lists are always
sorted the same way.
> Index: usr.sbin/bgpd/parse.y
> ===================================================================
> RCS file: /mount/openbsd/cvs/src/usr.sbin/bgpd/parse.y,v
> retrieving revision 1.414
> diff -u -p -r1.414 parse.y
> --- usr.sbin/bgpd/parse.y 2 Mar 2021 09:45:07 -0000 1.414
> +++ usr.sbin/bgpd/parse.y 14 Apr 2021 21:09:47 -0000
> @@ -3558,6 +3558,28 @@ symget(const char *nam)
> }
>
> static int
> +cmpcommunity(struct community *a, struct community *b)
> +{
> + if (a->flags > b->flags)
> + return 1;
> + if (a->flags < b->flags)
> + return -1;
> + if (a->data1 > b->data1)
> + return 1;
> + if (a->data1 < b->data1)
> + return -1;
> + if (a->data2 > b->data2)
> + return 1;
> + if (a->data2 < b->data2)
> + return -1;
> + if (a->data3 > b->data3)
> + return 1;
> + if (a->data3 < b->data3)
> + return -1;
> + return 0;
> +}
> +
> +static int
> getcommunity(char *s, int large, u_int32_t *val, u_int32_t *flag)
> {
> long long max = USHRT_MAX;
> @@ -4396,16 +4418,17 @@ filterset_add(struct filter_set_head *sh
> switch (s->type) {
> case ACTION_SET_COMMUNITY:
> case ACTION_DEL_COMMUNITY:
> - if (memcmp(&s->action.community,
> - &t->action.community,
> - sizeof(s->action.community)) < 0) {
> + switch (cmpcommunity(&s->action.community,
> + &t->action.community)) {
> + case -1:
> TAILQ_INSERT_BEFORE(t, s, entry);
> return;
> - } else if (memcmp(&s->action.community,
> - &t->action.community,
> - sizeof(s->action.community)) == 0)
> + case 0:
> break;
> - continue;
> + case 1:
> + continue;
> + }
> + break;
> case ACTION_SET_NEXTHOP:
> /* only last nexthop per AF matters */
> if (s->action.nexthop.aid <
> Index: regress/usr.sbin/bgpd/config/bgpd.conf.10.ok
> ===================================================================
> RCS file:
> /mount/openbsd/cvs/src/regress/usr.sbin/bgpd/config/bgpd.conf.10.ok,v
> retrieving revision 1.6
> diff -u -p -r1.6 bgpd.conf.10.ok
> --- regress/usr.sbin/bgpd/config/bgpd.conf.10.ok 17 Jul 2019 10:27:50
> -0000 1.6
> +++ regress/usr.sbin/bgpd/config/bgpd.conf.10.ok 14 Apr 2021 21:14:42
> -0000
> @@ -40,4 +40,4 @@ match from any large-community 1234:5678
> match from any large-community 1234:5678:1 large-community 1234:5678:2
> large-community 1234:5678:3
> match from any community 1234:1 large-community 1234:5678:1
> match from any large-community 1234:5678:1 community 1234:1
> -match from any set { community delete 1234:5678 community delete 1234:*
> community delete *:5678 community delete local-as:5678 community delete
> local-as:neighbor-as large-community delete 1234:15:5678 large-community
> delete *:15:5678 large-community delete local-as:15:5678 large-community
> delete local-as:15:* large-community delete local-as:15:neighbor-as
> large-community delete local-as:*:* community 1234:5678 community
> local-as:5678 community local-as:neighbor-as large-community 1234:15:5678
> large-community local-as:15:5678 large-community local-as:15:neighbor-as }
> +match from any set { community delete 1234:5678 large-community delete
> 1234:15:5678 community delete *:5678 large-community delete *:15:5678
> community delete local-as:5678 large-community delete local-as:15:5678
> community delete 1234:* community delete local-as:neighbor-as large-community
> delete local-as:15:* large-community delete local-as:*:* large-community
> delete local-as:15:neighbor-as community 1234:5678 large-community
> 1234:15:5678 community local-as:5678 large-community local-as:15:5678
> community local-as:neighbor-as large-community local-as:15:neighbor-as }
> Index: regress/usr.sbin/bgpd/config/bgpd.conf.11.ok
> ===================================================================
> RCS file:
> /mount/openbsd/cvs/src/regress/usr.sbin/bgpd/config/bgpd.conf.11.ok,v
> retrieving revision 1.5
> diff -u -p -r1.5 bgpd.conf.11.ok
> --- regress/usr.sbin/bgpd/config/bgpd.conf.11.ok 17 Jul 2019 10:27:50
> -0000 1.5
> +++ regress/usr.sbin/bgpd/config/bgpd.conf.11.ok 14 Apr 2021 21:14:09
> -0000
> @@ -33,7 +33,7 @@ match from any ext-community ovs invalid
> match from any ext-community ovs not-found
> match from any ext-community rt 64496:201 ext-community soo 64496:202
> match from any ext-community rt 64496:301 ext-community soo 4200000001:302
> ext-community odi 127.0.0.1:303
> -match from any set { ext-community delete ovs valid ext-community delete odi
> 127.0.0.1:6003 ext-community delete soo 4200000001:6002 ext-community delete
> ort 0x123456789abf ext-community delete rt 64496:6001 ext-community ovs valid
> ext-community odi 127.0.0.1:5003 ext-community soo 4200000001:5002
> ext-community ort 0x123456789abc ext-community rt 64496:5001 }
> +match from any set { ext-community delete ovs valid ext-community delete ort
> 0x123456789abf ext-community delete rt 64496:6001 ext-community delete odi
> 127.0.0.1:6003 ext-community delete soo 4200000001:6002 ext-community ovs
> valid ext-community ort 0x123456789abc ext-community rt 64496:5001
> ext-community odi 127.0.0.1:5003 ext-community soo 4200000001:5002 }
> match from any ext-community * *
> match from any ext-community rt *
> match from any ext-community soo *
> @@ -47,7 +47,7 @@ match from any ext-community rt 127.0.0.
> match from any ext-community soo 64496:*
> match from any ext-community soo 4200000001:*
> match from any ext-community soo 127.0.0.1:*
> -match from any set { ext-community delete odi 127.0.0.1:* ext-community
> delete soo 4200000001:* ext-community delete rt 64496:* ext-community delete
> mac-mob * ext-community delete ovs * ext-community delete rt * ext-community
> delete soo * ext-community delete odi * ext-community delete ort * }
> +match from any set { ext-community delete ort * ext-community delete mac-mob
> * ext-community delete ovs * ext-community delete rt * ext-community delete
> soo * ext-community delete odi * ext-community delete rt 64496:*
> ext-community delete odi 127.0.0.1:* ext-community delete soo 4200000001:* }
> match from any ext-community rt 64496:local-as
> match from any ext-community soo 4200000001:local-as
> match from any ext-community odi 127.0.0.1:local-as
>
--
:wq Claudio