Showing posts with label Object Identifier. Show all posts
Showing posts with label Object Identifier. Show all posts

Friday, 3 October 2014

Line of Codes

Now the essential part of MIB Parser is completed and achieved its objective.

Here is LoC required to get it to current state.

  • Xtext (134 lines)
  • Xcore ( 107 lines)
  • Java (6 lines)
  • Xtend (27 lines)
  • Acceleo (31 lines)

Some of the xtend codes that I written earlier for scoping is not counted as its deemed as not required once I understand namespace concept in Xtext.

Generate Oid list from Mib model

To generate Oid list (i.e text file) from Mib model, there are a few readily available Model to Text Transformation (M2T) tools for EMF.
I have started this work on Acceleo, and find the editor's content assist is pretty good and and straight forward way to apply launcher menu for mib files - almost no coding except the template declaration which is based on MOFM2T.

I will try to detail the steps clearly as I could for others to benefit. I struggled to get these end to end steps correct as most of tutorials out there are by features and less based on use-case (on top of that I used Xcore for model, hence it was a blocker at start).
  1. Install Acceleo from Modelling Component place (Version: 3.5.1), and change to Acceleo perspective, this makes lots of handy tool/wizard simple to find as oppose continue working on Java perspective.
  2. Acceleo Create Project wizard does not recognize Xcore as model. Therefore, I had to generate Ecore model first. Choose Mib.xcore from Package Explorer, and click "new -> Other..", choose EMF Generator Model. This will generate both Ecore and genmodel.
  3. Create a new Acceleo project "com.ravi.mib.acceleo.module.oid". On second wizard page - "Create a new Acceleo generation file", change module name to "oid" and search for Mib model from "Runtime Version" (http://www.ravi.com/ibm/xtext/Mib). Change template name to "generateOid" and type to "MibModel"
  4. Once the project created, edit com/ravi/mib/acceleo/module/oid/common/oid.mtl file and apply following template.
  5. oid.mtl
    [comment encoding = UTF-8 /]
    [module oid('http://www.ravi.com/mib/xtext/Mib')]
    
    [template public generateOID(model : MibModel)]
     [comment @main /]
     [for (d : Definition | model.definitions)]
      [file (d.name.toString().concat('.oid'), false, 'UTF-8')]
       [for (oid : Identifier | d.identifiers)]
        [if (isValidObjectType(oid))]
    [oid.name/],[oid.value.oid/],[getPrimitive(oid)/],[getDerived(oid)/]
        [/if]
       [/for]
      [/file]
     [/for]
    [/template]
    
    [query private isValidObjectType(oid : Identifier) : Boolean = 
     oid.oclIsTypeOf(ObjectType) and
     not oid.oclAsType(ObjectType).type.typeName.oclIsUndefined() and
     oid.oclAsType(ObjectType).type.typeName.toString().strcmp('OBJECT IDENTIFIER') <> 0
    /]
    
    [query private getPrimitive(oid : Identifier) : String =
      if oid.oclAsType(ObjectType).type.dataType.derived.name.oclIsUndefined() then
      ''
     else
      oid.oclAsType(ObjectType).type.dataType.derived.name.toString()
     endif
    /]
    
    [query private getDerived(oid : Identifier) : String = 
     oid.oclAsType(ObjectType).type.typeName.toString()
    /]
    

  6. There will be an error afterwards for "oid.common" package to be exported. Do as suggested.
  7. Now for launcher menu, select earlier created Acceleo project from Package Explorer and choose new Acceleo UI Launcher project, On "Acceleo UI Launcher settings", change model file name filter to "*.mib" and target folder access to "...getFolder("oid")".
  8. Finally modify label for menu as "Mib Generator"
  9. Once eclipse instance is launched, Generate Oid option should available for mib files.
RFC1213-MIB.oid
sysDescr,1.3.6.1.2.1.1.1,DisplayString,OCTET STRING
sysUpTime,1.3.6.1.2.1.1.3,TimeTicks,INTEGER
sysContact,1.3.6.1.2.1.1.4,DisplayString,OCTET STRING
sysName,1.3.6.1.2.1.1.5,DisplayString,OCTET STRING
sysLocation,1.3.6.1.2.1.1.6,DisplayString,OCTET STRING
sysServices,1.3.6.1.2.1.1.7,,INTEGER
ifNumber,1.3.6.1.2.1.2.1,,INTEGER
ifIndex,1.3.6.1.2.1.2.2.1.1,,INTEGER
ifDescr,1.3.6.1.2.1.2.2.1.2,DisplayString,OCTET STRING
ifType,1.3.6.1.2.1.2.2.1.3,,INTEGER
ifMtu,1.3.6.1.2.1.2.2.1.4,,INTEGER
ifSpeed,1.3.6.1.2.1.2.2.1.5,Gauge,INTEGER
ifPhysAddress,1.3.6.1.2.1.2.2.1.6,PhysAddress,OCTET STRING
ifAdminStatus,1.3.6.1.2.1.2.2.1.7,,INTEGER
ifOperStatus,1.3.6.1.2.1.2.2.1.8,,INTEGER
ifLastChange,1.3.6.1.2.1.2.2.1.9,TimeTicks,INTEGER
ifInOctets,1.3.6.1.2.1.2.2.1.10,Counter,INTEGER
ifInUcastPkts,1.3.6.1.2.1.2.2.1.11,Counter,INTEGER
ifInNUcastPkts,1.3.6.1.2.1.2.2.1.12,Counter,INTEGER
ifInDiscards,1.3.6.1.2.1.2.2.1.13,Counter,INTEGER
ifInErrors,1.3.6.1.2.1.2.2.1.14,Counter,INTEGER
ifInUnknownProtos,1.3.6.1.2.1.2.2.1.15,Counter,INTEGER
ifOutOctets,1.3.6.1.2.1.2.2.1.16,Counter,INTEGER
ifOutUcastPkts,1.3.6.1.2.1.2.2.1.17,Counter,INTEGER
ifOutNUcastPkts,1.3.6.1.2.1.2.2.1.18,Counter,INTEGER
ifOutDiscards,1.3.6.1.2.1.2.2.1.19,Counter,INTEGER
ifOutErrors,1.3.6.1.2.1.2.2.1.20,Counter,INTEGER
ifOutQLen,1.3.6.1.2.1.2.2.1.21,Gauge,INTEGER
atIfIndex,1.3.6.1.2.1.3.1.1.1,,INTEGER
TODO: Is there any way for Xcore to register its model URI so that Acceleo able to recognize without going through Ecore generation?

TODO: How to limit OID list down to the selected mib file alone?

Tuesday, 30 September 2014

Completing Data Type reference in Xtext Grammar

As described in overview from the first post, its almost close to produce CSV artefacts containing OID short name, Oid in dot notation number, derived data type and its primitive data type.

The part missing from model now is the data type information. This can be completed with following modification to Xtext grammar and Xcore.


Mib.xtext
ObjectType:
 name=ID imp=[Macro] 
 'SYNTAX' type=mibType2
 'ACCESS' access=AccessEnum 
 'STATUS' status=StatusEnum 
 ('DESCRIPTION' description=STRING)? 
 ('REFERENCE' reference=STRING)? 
 ('INDEX' '{' mibType (',' mibType)* '}')? 
 ('DEFVAL' '{' INT | STRING '}')? 
 value=OidValue;

ObjectType class will now contain feature type of mibType2 among others. mibType2 is similiar to mibType, the reason I have created another instance of mibType is as it used in lot of places such as Macro, Object Type Index, Choice etc. All these rightfully need to be changed as well, however for now I want to keep it simple - it can be overwhelming otherwise.


Mib.xtext
mibType2:
 (sequence?=SequenceOf)? 
 dataType=DataType
 ('(' 'SIZE' '(' (INT '..')? INT ')'')')? 
 ('(' (INT '..')? (INT | 'MAX') ')')? 
 ('{' ID '(' INT ')' (',' ID '(' INT ')')* '}')?;

DataType:
 name=(OctectString | 'INTEGER' | ObjectIdentifier) |
 derived=[TypeDefinition];

SequenceOf:
 'SEQUENCE' 'OF';
 
ObjectIdentifier:
 'OBJECT' 'IDENTIFIER';

OctectString:
 'OCTET' 'STRING';


One trick I learned here is that if there are multiple keywords make up a syntax, its better to push those down to its own rule e.g SequenceOf - Xtext  intelligent enough to know this is terminal like rule and will not create an EClass for it.

Datatype takes primitive data types (3 types) or a derived data type from TypeDefinition.  Note that this 'TypeDefinition' used to be called 'DataType' earlier - re-factored to reflect semantic better.


Mib.xtext
Definition:
 name=ID 'DEFINITIONS' '::=' 'BEGIN'
 Export?
 imports=Import?
 (identifiers+=Identifier | typedef+=TypeDefinition | macros+=Macro)+
 'END';

TypeDefinition:
 name=ID '::=' ('[' 'APPLICATION' INT ']')? 
 'IMPLICIT'? (Choice | Sequence | type=mibType2);

And to reflect this on Xcore, following need to be changed:


Mib.xtext
class Definition {
 String name
 contains Import imports
 contains Identifier[] identifiers
 contains TypeDefinition[] typedef
 contains Macro[] macros
}

class TypeDefinition {
 String name
 contains mibType2 ^type
}

Setting TypeDefinition as containment for Definition allows Object Type's type to refer to this.

Mib.xtext
class ObjectType extends Identifier {
 refers Macro imp
 contains mibType2 ^type
 AccessEnum access
 StatusEnum status
 String description
 String reference
}

enum AccessEnum {
 readOnly as "read-only"
 readWrite as "read-write" = 1
 writeOnly as "write-only" = 2
 notAccessible as "not-accessible" = 3
}

enum StatusEnum {
 mandatory
 optional = 1
 obsolete = 2
 deprecated = 3
}

Now running this will give full "open declaration" for type with derived data type as well.


Tuesday, 9 September 2014

Object Type should extends from Object Identifier

In MIB, there are 2 ways to define Identifier Objects; as Object-Identifier and Object-Type.

RFC1213-MIB.mib
          -- Object Identifier
          mib-2      OBJECT IDENTIFIER ::= { mgmt 1 }

          -- Object Type
          sysDescr OBJECT-TYPE
              SYNTAX  DisplayString (SIZE (0..255))
              ACCESS  read-only
              STATUS  mandatory
               DESCRIPTION
                      "A textual description of the entity.  This value
                      should include the full name and version
                      identification of the system's hardware type,
                      software operating-system, and networking
                      software.  It is mandatory that this only contain
                      printable ASCII characters."
              ::= { system 1 }


Object-Identifier basically contains OID name and OID value where else Object-Type contains these as well few more additional attributes.

In another word, Object-Type EClass should extend from Object-Identifier EClass. This can be done via Xtext declarative way:

Mib.xtext
Definition:
 name=ID 'DEFINITIONS' '::=' 'BEGIN'
 Export?
 imports=Import?
 (identifiers+=Identifier | DataType)+
 'END';

Object:
 name=ID;

Identifier:
 ObjectType | (name=Object mibType value=OidValue);

ObjectType:
 name=Object imp=[Object] 'SYNTAX' mibType 'ACCESS' ID 'STATUS' ID
 ('DESCRIPTION' STRING)?
 ('REFERENCE' STRING)?
 ('INDEX' '{' mibType (',' mibType)* '}')?
 ('DEFVAL' '{' INT | STRING '}')?
 value=OidValue;



This generates following ecore model: