Hi Ondrej,

Thanks for the feedback.

On 1/6/20 3:16 AM, Ondrej Zajicek wrote:
Thanks for the patchset, sorry for not giving feedback sooner, was on
vacation.

No problem, I was expecting that. I am also first responding now, since I
have been under the weather for the past few days.


If i understand it correctly, the main point of this patchset is to
introduce 'typed symbols', which have multiple values based of network
type of processed route.

Correct. The patches allows for explicitly typed constants, filters and
functions. If a filter or function uses a typed symbol, it will implicitly
be typed itself. Once the context is know that version of the filter will
be generated.


I must say that i do not like the approach taken in the patch, seems to
me that for intended purpose it is too intrusive change and the feature
is too idiosyncratic - i don't recall any language where a constant may
represent multiple unrelated values based on context.

I agree that the patch set is a little intrusive, but I decided that it
was good enough for a PoC and to get the discussion started, hence
labeling it as an RFC patch.


In bird 1 it was possible to have bird4.conf and bird6.conf share common
configuration files, but have 2 different files defining symbols.

In bird 2 this ends out with a lot of symbols ending in "4" or "6",
and quite a few case statements or to do address family specific processing.
The case statements could be hidden behind a case-function per data type.

function get_typed_pfx_set(prefix set v4; prefix set v6)
{
        case net.type {
                NET_IP4: return v4;
                NET_IP6: return v6;
        }
}

Even this leads to long lines like: get_typed_pfx_set(AS65000_prefixes4, 
AS65000_prefixes6),
including the need to pass both prefix sets, through generic filtering 
functions.
Overall leading to an idiosyncratic config.

I would hope that people would only use this feature to store related values,
however I have only enforced that they must have the same data type.


It is also over-specific (dispatch hardcoded for net_type, while there
are other, context-specific properties, like protocol type).
I made the syntax and symbol part very net_type specific, since I'm not aware
of other context parameters where it would make a lot of sense.

I specifically choose not allow a fallback value, ie. calling cf_error
if a symbol is not defined for a given net_type.

With protocol typing I see it as more useful for protocol specific
overrides, so maybe a fallback value should be allowed?

Does anybody else have any feedback on this?


One way to make it less intrusive would be to keep symbol table the same
(just symbol->value mapping) and do the change just in 'value' part.
I don't have a problem with converting it to a linked list of versions of the 
symbol.


You have this example:

define default_route:ipv4 = 0.0.0.0/0;
define default_route:ipv6 = ::/0;

This could be done by using function instead of constant:

function default_route()
{
   case net.type
   {
     NET_IP4: return 0.0.0.0/0;
     NET_IP6: return ::/0;
   }
}
>
I agree that it is more cumbersome than your version.

I used default route mostly as an easy to understand example, the big
benefit comes with prefix filtering hence the reference to bgpfilterguide.


Seems to me that your intended objective could be achieved, while keeping
it universal and reasonable, by several independent changes:

1) Allow 'lazy-evaluated constants', that could depend on context. These
are essentially zero-argument functions in disguise.
>
2) Allow something like if/case expressions (instead of just statements).

3) (optional) partially-evaluate/adapt filters based on context.

When we originally discussed this idea during RIPE78 in Reykjavik, we also
talked about that it should be possible to optimize it parse time.

Therefore I wanted to explore the feasibility of doing that, the shortcut
I took here, by only having a thin adaptation layer, is that I had to mark
it as never constant. That could be fixed by moving most of the linearization
work to the adaptation state, leaving only a loop check the current
linearization stage.

The benefit of doing the adaptation at parse time, means that non-existent
variants of a symbol can be revealed before a new config is loaded.

The redundant case statements during run-time is not an issue for us,
but I imagine it could be to some of the route server operators.


So one could wrote something like:

define default_route = case net.type {
   NET_IP4: 0.0.0.0/0;
   NET_IP6: ::/0;
}
This syntax could work, but should just result in the entries being put in
a linked-list under the symbol, so that it can be guaranteed that they all have
the same type.

I prefer to be able to define constants as several individual statements.

If constants can be defined for other parameters than net_type, should then
also be possible to do it multi-dimensional? Fx. for ipv4 in protocol x.


(The remaining wart is a current style of enum constants, like 'NET_IP4'.)

I'm aware that net.type uses the C constants, but I choose to use `net_type`,
since it is consistent with table and channel type definitions.


--
Best regards
Asbjørn Sloth Tønnesen

Reply via email to