[Click] "Graft" ports

Cliff Frey cliff at meraki.com
Fri Jan 28 14:08:26 EST 2011


Eddie very recently made changes to the parser, allowing for new syntax and
types of connections, so I would look at his recent commits.

Cliff

On Fri, Jan 28, 2011 at 11:05 AM, Philip Prindeville <
philipp_subx at redfish-solutions.com> wrote:

> On 1/21/11 6:48 PM, Eddie Kohler wrote:
>
>> On 01/21/2011 05:42 PM, Philip Prindeville wrote:
>>
>>> The original concern (with exposing global objects into the guts of an
>>> elementclass) was that this would only work for a single instance is
>>> valid...
>>> that is, if A imports B, then you can only have a single object of class
>>> A.
>>>
>>
>> No, you could have many.  But any element of class A will refer to the
>> same imported element.  Sometimes that's not what you want.  Sometimes it
>> is.
>>
>> The idea of "default connections" is interesting -- "include this
>> connection only if the port was previously unused."  You could get a
>> somewhat similar effect with compound element overloading, but only somewhat
>> similar.
>>
>> Eddie
>>
>
> What's involved in coding up a patch for prototype testing?
>
> I've not looked into the innards of the click parser and intermediate code
> generator.
>
> Thanks.
>
> -Philip
>
>
>
>  The advantage of graft points was that you'd have to plumb instances
>>> individually, same as for input and output ports.
>>>
>>> My only point about graft point was that (a) they would simplify keeping
>>> track
>>> of indices on complex objects (especially for objects that are generated
>>> from
>>> scripts with variable numbers of inputs and outputs); (b) they would
>>> simplify
>>> notation by specifying both input and output to the grafted-to object at
>>> the
>>> same time, and (c) they would impose rules about graft points being used
>>> in
>>> pairs that doesn't exist for inputs and outputs which are orthogonal to
>>> each
>>> other (at least with respect to an object's perspective of the outside
>>> world).
>>>
>>> I thought about it some more, and if the default for any unspecified
>>> (graft)
>>> connection was :: { input -> output } then that would make it very easy
>>> to
>>> "pepper" an object with various inspection and instrumentation points, or
>>> points where you might later want to apply additional processing on a
>>> packet
>>> as it flows through the innards of a class.
>>>
>>> I could easily foresee a complex object where I had graft points for:
>>>
>>> [0] the packet at ingress;
>>> [1] the packet after it has SNATting performed;
>>> [2] the packet after deep inspection into layer 7 and rewriting of
>>> addresses;
>>> [3] resetting the timer on the association;
>>> ...
>>> [n] the packet at egress;
>>>
>>> And you wouldn't need to recode an object to add to peek into it at
>>> various
>>> well-known (and previously defined) places.
>>>
>>> Like I said: graft points are just a notational convenience. At the end
>>> of the
>>> day, they would just map into pairs of input and output ports... but the
>>> implementation would be handled by the preprocessor.
>>>
>>>
>>> On 1/21/11 4:47 PM, Eddie Kohler wrote:
>>>
>>>> Hey, a couple points.
>>>>
>>>> (1) Unlike Cliff and Ian, I see some value for importing external
>>>> elements
>>>> into a compound. Perhaps a statement like "import(ELEMENTNAME)" would be
>>>> required. Although new errors could happen, they'd be pretty easy to
>>>> understand even now, and the messages could be improved.
>>>>
>>>> (2) On the below, we generally write debuggers like this:
>>>>
>>>> // elementclass Debugger {$tag | input -> output};
>>>> elementclass Debugger {$tag | input -> IPPrint($tag, MAXLENGTH 64) ->
>>>> output};
>>>>
>>>> Then you refer to Debugger as an element.
>>>>
>>>> I want to note that graft points as used in THIS mail are supported now;
>>>> they are implemented as normal inputs and outputs. I don't understand
>>>> what
>>>> you gain by treating grafts as separate from normal inputs and outputs.
>>>> They
>>>> must always be connected or there are errors.
>>>>
>>>> Eddie
>>>>
>>>>
>>>> On 01/20/2011 04:11 PM, Philip Prindeville wrote:
>>>>
>>>>> One other nice property about graft-points is this:
>>>>>
>>>>> elementclass MyIncrediblyHairyObject {
>>>>> ...
>>>>> }
>>>>>
>>>>> miho :: MyIncrediblyHairyObject;
>>>>> ...
>>>>>
>>>>> miho [0]<-> null :: { input -> output }<-> [0] miho;
>>>>> // miho [0]<-> dbg0 :: { IPPrint("Inspection 0", MAXLENGTH=64) }<-> [0]
>>>>> miho;
>>>>>
>>>>>
>>>>> and by just moving the comment prefix around, I can turn on or off
>>>>> debugging, without having to disturb the body of the elementclass
>>>>> itself.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> On 1/20/11 3:59 PM, Philip Prindeville wrote:
>>>>>
>>>>>> I've been thinking about this some more...
>>>>>>
>>>>>> If I have the following:
>>>>>>
>>>>>> elementclass Foo {
>>>>>>
>>>>>> stuff1 -> external-object -> stuff2;
>>>>>>
>>>>>> }
>>>>>>
>>>>>> then this can be rewritten as:
>>>>>>
>>>>>> elementclass Foo {
>>>>>> stuff1 -> [N] output;
>>>>>> input [M] -> stuff2;
>>>>>> }
>>>>>>
>>>>>> f :: Foo;
>>>>>>
>>>>>> f [N] -> external-object -> [M] f;
>>>>>>
>>>>>> I'd like to propose a notational convenience called "graft" (as in a
>>>>>> graft-point).
>>>>>>
>>>>>> graft[0] would be short-hand for 1+ the highest used input, and [0]
>>>>>> graft
>>>>>> would be 1+ the highest used input.
>>>>>>
>>>>>> (and so on for [1], [2], etc.)
>>>>>>
>>>>>> We'd need a new operator for graft-points. Maybe:
>>>>>>
>>>>>> f [G]<-> [a] external-object [b]<-> [G] f;
>>>>>>
>>>>>> it would be a syntactic error to mismatch subscripts for the object
>>>>>> being
>>>>>> grafted to.
>>>>>>
>>>>>> The notation inside the elementclass would be:
>>>>>>
>>>>>> elementclass Foo {
>>>>>> stuff1 -> graft [G] -> stuff2; // or ... [G] graft ...
>>>>>> }
>>>>>>
>>>>>> Does that make sense?
>>>>>>
>>>>>> -Philip
>>>>>>
>>>>>>
>>>>>> On 1/18/11 3:43 PM, Beyers Cronje wrote:
>>>>>>
>>>>>>> The config you posted below Ian explicitly states "This would be
>>>>>>> legal:" at
>>>>>>> the top. I think Ian is referring to the second config that will
>>>>>>> cause
>>>>>>> issues:
>>>>>>>
>>>>>>> "
>>>>>>> I think this should complain that fd[0] is being used twice (port
>>>>>>> connection error), although it may take a minute to see why that's
>>>>>>> the
>>>>>>> case (and would be much trickier to see in a more complex config):
>>>>>>> --------------------------------------
>>>>>>> fd::FromDevice(...);
>>>>>>>
>>>>>>> elementclass Bar {
>>>>>>> fd[0] -> Print() -> [0]output;
>>>>>>> }
>>>>>>>
>>>>>>> a::Bar() -> Discard();
>>>>>>> b::Bar() -> Discard();
>>>>>>> --------------------------------------
>>>>>>> "
>>>>>>>
>>>>>>>
>>>>>>> On Wed, Jan 19, 2011 at 12:32 AM, Philip Prindeville<
>>>>>>> philipp_subx at redfish-solutions.com> wrote:
>>>>>>>
>>>>>>>  On 1/18/11 7:34 AM, Ian Rose wrote:
>>>>>>>>
>>>>>>>>> If I am thinking this through correctly, IMHO it wouldn't be a good
>>>>>>>>> idea
>>>>>>>>> to allow elementclasses to do this. Reason being that in some cases
>>>>>>>>> you
>>>>>>>>> could create port connection errors merely through declaring
>>>>>>>>> multiple
>>>>>>>>> elements of your new elementclass type. This would be an unexpected
>>>>>>>>> and
>>>>>>>>> confusing error since its impossible to do currently. AFAIK
>>>>>>>>> currently
>>>>>>>>> there are no errors that can occur merely by *declaring* too many
>>>>>>>>> elements of some type. So this would introduce a whole new category
>>>>>>>>> of
>>>>>>>>> error. Some examples:
>>>>>>>>>
>>>>>>>>> This would be legal:
>>>>>>>>> --------------------------------------
>>>>>>>>> fd::FromDevice(...);
>>>>>>>>>
>>>>>>>>> elementclass Bar {
>>>>>>>>> fd[0] -> Print() -> [0]output;
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> a::Bar() -> Discard();
>>>>>>>>> --------------------------------------
>>>>>>>>>
>>>>>>>>> I think this should complain that fd[0] is being used twice (port
>>>>>>>>> connection error), although it may take a minute to see why that's
>>>>>>>>> the
>>>>>>>>> case (and would be much trickier to see in a more complex config):
>>>>>>>>>
>>>>>>>> Sorry, not seeing why the above case represents using the port
>>>>>>>> twice...
>>>>>>>>
>>>>>>>>
>>>>>>>>  --------------------------------------
>>>>>>>>> fd::FromDevice(...);
>>>>>>>>>
>>>>>>>>> elementclass Bar {
>>>>>>>>> fd[0] -> Print() -> [0]output;
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> a::Bar() -> Discard();
>>>>>>>>> b::Bar() -> Discard();
>>>>>>>>> --------------------------------------
>>>>>>>>>
>>>>>>>>> In order to cause this same error currently (without the proposed
>>>>>>>>> elementclass enhancement) you'd have to do this, which I think
>>>>>>>>> makes the
>>>>>>>>> error more obvious:
>>>>>>>>> --------------------------------------
>>>>>>>>> fd::FromDevice(...);
>>>>>>>>>
>>>>>>>>> elementclass Bar {
>>>>>>>>> input[0] -> Print() -> [0]output;
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> fd[0] -> a::Bar() -> Discard();
>>>>>>>>> fd[0] -> b::Bar() -> Discard();
>>>>>>>>> --------------------------------------
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Just my $0.02.
>>>>>>>>>
>>>>>>>>> - Ian
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On 01/17/2011 07:55 PM, Philip Prindeville wrote:
>>>>>>>>>
>>>>>>>>>> Yeah, it especially makes sense to have arpfoo be global if it
>>>>>>>>>> needs to
>>>>>>>>>>
>>>>>>>>> be accessible from two different elementclass's, one that deals
>>>>>>>> with the IP
>>>>>>>> flow (input [0] and output [0]) and another one that deals strictly
>>>>>>>> with
>>>>>>>> the
>>>>>>>> ARP request/reply flow (input [1] and output [1]).
>>>>>>>>
>>>>>>>>> Someone else will have to come up with the patches... I've not yet
>>>>>>>>>>
>>>>>>>>> dabbled in the code itself.
>>>>>>>>
>>>>>>>>>
>>>>>>>>>> On 1/17/11 4:35 PM, Eddie Kohler wrote:
>>>>>>>>>>
>>>>>>>>>>> Hi Philip,
>>>>>>>>>>>
>>>>>>>>>>> I can see why you thought compound elements would work that way,
>>>>>>>>>>> but
>>>>>>>>>>>
>>>>>>>>>> they don't. They are very strictly encapsulated: all connections
>>>>>>>> to other
>>>>>>>> elements must take place through explicit inputs and outputs.
>>>>>>>>
>>>>>>>>> I admit it would make sense to do it the way you've imagined.
>>>>>>>>>>> Patches
>>>>>>>>>>>
>>>>>>>>>> welcome...
>>>>>>>>
>>>>>>>>> Eddie
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> On 1/15/11 2:53 PM, Philip Prindeville wrote:
>>>>>>>>>>>
>>>>>>>>>>>> I've got a configuration where I do:
>>>>>>>>>>>>
>>>>>>>>>>>> ...
>>>>>>>>>>>> arpfoo :: ARPQuerier(...);
>>>>>>>>>>>>
>>>>>>>>>>>> elementclass Bar {
>>>>>>>>>>>> ...
>>>>>>>>>>>> class :: classifier(...);
>>>>>>>>>>>> ...
>>>>>>>>>>>> class [2] -> [1] arpfoo;
>>>>>>>>>>>> ...
>>>>>>>>>>>> }
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> but it complains that "unknown element class 'arpfoo'" in a few
>>>>>>>>>>>>
>>>>>>>>>>> places, and that input 1 isn't used...
>>>>>>>>
>>>>>>>>> So I'm confused. Everything is scoped globally... even stuff
>>>>>>>>>>>> defined
>>>>>>>>>>>>
>>>>>>>>>>> within an elementclass gets scoped globally.
>>>>>>>>
>>>>>>>>> Why then can't I access a global variable from within an
>>>>>>>>>>>>
>>>>>>>>>>> elementclass's scope?
>>>>>>>>
>>>>>>>>> What am I missing?
>>>>>>>>>>>>
>>>>>>>>>>>> Thanks,
>>>>>>>>>>>>
>>>>>>>>>>>> -Philip
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>
>>>>>>
>>>>>
>>>
>


More information about the click mailing list