[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

SMIng notation enhancements for size/range/enums




[I'm not sure how appropriate it is to submit an ID for these things without
some initial discussion, and I don't think I will be able to make it to
the December WG meeting.. But I can do an ID-style document if there
is interest.]

Current SMI versions have several limitations when it comes to describing
objects with constraints or refined syntax:

   * There is no way to define an object or data type with value constraints
     that are tied directly to the operation being performed on the object.
     (Example: RowStatus).

   * Definitions that have a single minimum size or range that MUST be
     supported, and a maximum that MAY be supported require a separate
     "MODULE-COMPLIANCE" type definition to define the minimum, just as
     if there were multiple levels of conformance with different minima.

   * There is no way to specify a maximum size or range for different
     "compliance" levels that specify distinct classes of devices with
     different constraints on the same object (Example: docsDevRole,
     for which CM can only have the value cm(1), and a CMTS can only
     have the values cmtsActive(2) or cmtsBackup(3)).

I believe Methods (which are listed as a "nice to have" feature), along
with a change to the way sizes/ranges are specified, can be used to
address these limitations in a reasonably simple and SMIv1/v2-mappable
manner.  I'd like to start with a change to the size/range format in this
message, and save talking a bit about methods and how they could be
combined with it for a separate message.


The current method of specifying a size or range for a numeric or string
type use a parenthesized notation with vertical bars separating discreet
subranges, such as (0|5..10|20).  Instead of a single set of parentheses
and veritcal bars, I proposes adopting a notation similar to that used in
mathematics:

The L-Paren character '(' followed by a number is taken to mean all
previously allowed values up to and including the given number.

The R-Paren character ')' preceded by a number is taken to mean all
from the number up through all previously allowed values.

The L-Bracket character '[' followed by a number is taken to mean a strict
starting value for a subrange that excludes values lower than the given
number.

The R-Bracket character ']' preceded by a number is taken to mean a strict
ending value for a subrange that excludes values higher than the
given number.

In other words, bracketed '[]' notation carries the same "exclusive"
meaning as the current parenthetical '()' notation used by SMIv1 and SMIv2
for a discreet subrange, while the parenthetical notation is used to
define a subrange that does not exclude previously allowed values.
For example, "(0|10..12)" in SMIv1 would be "[0][10..12]" in SMIng.

Where this becomes useful is in definitions that refine the constraints
of the base or derived type used, where a minimum level for conformance
must be specified, or where ONLY certain values are allowed for certain
operations or conformance levels (really, device subclasses).

Take, for a contrived example, a generic 255-character max string datatype
such as DisplayString.  It would be defined with a syntax of...

    OctetString(SIZE[0..255]).

Now, consider a specific string object that must support a non-zero minimum
length string (say, 10 octets), but is still free to have a longer value.
This would be defined with any of the following equivalent notations:

    DisplayString(SIZE[10))        ..or..
    DisplayString(SIZE[10..255))   ..or..
    DisplayString(SIZE[10..255])

Altenerately, a specific string object that has no minimum but has a strict
maximum length (say, 100 octets) may be defined with any of the following:

    DisplayString(SIZE(100])       ..or..
    DisplayString(SIZE(0..100])   ..or..
    DisplayString(SIZE[0..100])

Yes, the examples are contrived and doesn't describe a particularly useful
situation without greater detail.  But essentially the change to the
notation would eliminate the need for a MODULE-COMPLIANCE statement whose
sole purpose is to list a single "minimum" size/range requirement for
conformance.

However, there are a several other cases where it becomes more useful:

1. The same notation could be used for enumerated-type refinements to
describe enumerations that MUST be supported versus enumerations that
MAY be supported.  For example, a Textual Convention defined with normal
enumerated-integer syntax that lists 0, 1, 2 and 3 as named values, and an
object based on that TC that MUST support the value 0, 1 and 2 but need not
support 3:

    exampleTC ::= TEXTUAL CONVENTION
       ...
       SYNTAX INTEGER {
          unknown(0),
          on(1),
          off(2),
          standby(3)
       }

    someObject ::= OBJECT-TYPE
       ...
       SYNTAX exampleTC (0..2)
       ...
    ::= { ... }


The above would say that an implementation of 'someObject' MUST support
the values to 2, but due to the use of () instead of [] it is not
restricted to only those values -- instead, its actual constraints are
inherited from TC.  If you wanted an object based on 'exampleTC' that
allowed ONLY the values 0, 1 and 2, then it would be...

      SYNTAX exampleTC [0..2]

2. While this allows a lot of MODULE-COMPLIANCE information to be
condensed into the actual definitions, this opens up some new
possibilities for use in MODULE-COMPLIANCE.  In particular, this notation
could be used to define MC statements corresponding to distinct device
classes with their own fixed constraints on the same object(s).

You could, for example, define one MC for CM's and one for CMTS's, where
each has a variation for docsDevRole listing strict constraints on the
allowed values:

    cmBasicCompliance ::= MODULE-COMPLIANCE
        ...
        OBJECT docsDevRole
            SYNTAX INTEGER [1]       -- For CM

    cmtsBasicCompliance ::= MODULE-COMPLIANCE
        ...
        OBJECT docsDevRole
            SYNTAX INTEGER [2..3]    -- For CMTS

A device may claim compliance to BOTH of these MCs, of course (if you had
a dual-class device), in which case the constraints would be the union of
the two MCs.  In general, this provides a software-parseable way to
specify values that do and do not make functional sense (and thus MUST and
MUST NOT be accepted) for different device classes.

3. Further usefulness is attained when the new syntax combined with methods,
where different constraints apply to different operations/methods (such as
in the case of RowStatus).  But for purposes of discussing each feature
in their own right, I'll save that for a separate message.