Rule Manager

The Rule Manager manages the context(s) for a specific device or a set of devices. It maintains the context database and ensures its consistency. The hierarchy is the following:

  • context_database

    • device_context

      • set_of_rules

        • rule_id/rule_id_length

          • rules

            • Fragmentation

            • Compression

Introduction

The context includes a set of rules shared by both ends. Identical Rules are used on both ends. They can be simply copied/pasted from one end to the other end, if both ends use the same format for describing them.

This document specifies the OpenSCHC rule data model, which is based on JSON.

Rule definition

A rule is described as a JSON dictionary.

A rule is identified by its RuleID.

The size of the RuleID representation can change from one rule to the next. Therefore, the rule description includes a RuleIDLength that indicates the length of the RuleID, in bits.

Both fields are integer numbers:

{
"RuleID" : 12,
"RuleIDLength" : 4
# notice that RuleID 12 represented on 6 bits is different from RuleID 12 on 4 bits!
}

In SCHC, rules are used either for compression or fragmentation. Therefore, one and only one of the two keywords “fragmentation” or “compression” must be specified, per rule.

Compression Rules

As defined in the SCHC specification, compression rules are composed of Field Descriptions. The order in which the Field Descriptions appear in the rule is significant (e.g. it defines the order in which the compression residues are sent), therefore a compression rule is represented as an array.

The Field Description is a dictionary containing the key+data pairs as defined in the SCHC specification:

  • FID: a string identifying the field of the protocol header that is being compressed. The value of this string is the one returned by the protocol analyzer when encountering said field. E.g. “IPV6.VER”. <<< why is this not IP.VER instead? It seems to me that IPV6.VER will always be 6!>>>

  • FL: if the value is a number, that value expresses the length of the field, in bits. If the value is a string, it designates a function that can compute the field length. The functions currently defined are:

    • var: the field is of variable length. It will be determined at run time by the protocol analyzer. The length (expressed in bytes) will be transmitted as part of the compression residue. The encoding is described in the SCHC specification.

    • tkl: this function is specific for compressing the CoAP Token field. The length of the Token is determined at run time by the protocol analyzer by looking at the Token Length field of he CoAP header.

  • FP: an integer specifying the position in the header of the field this Field Description applies to. The default value is 1. For each recurrence of the same field in the header, the value is increased by 1.

  • DI: tells the direction to which this Field Description applies:

    • Up: only to uplink messages (i.e. from device to network)

    • Dw: only to downlink messages (i.e. from network to device)

    • Bi: to both directions

  • TV: specifies the Target Value. The value is a number, a string or an array of these types. The “TV” key can be omitted or its value set to null if there is no value to check, for instance together with the “ignore” MO. If the Target Value is an array, then the value null among the array elements indicates that the Field Descriptor matches the case where the field is not present in the header being compressed.

  • MO: specifies the Matching Operator. It is a string that can take the following values:

    • ignore: the field must be present in the header, but the value is not checked.

    • equal: type and value must check between the field value and the Target Value <<< il y a des champs avec des descriptions explicites de type dans les protocoles considérés ? >>

    • MSB: the most significant bits of the Target Value are checked against the most significant bits of the field value. The number of bits to be checked is given by the “MOa” field.

    • match-mapping: with this MO, the Target Value must be an array. This MO matches when one element of the Target Value array matches the field, in type and value.

  • MOa: specifies, if applicable, an argument to the MO. This currently only applies to the “MSB” MO, where the argument specifies the length of the matching, in bits.

  • CDA: designates the Compression/Decompression Action. It is a string that can take the following values:

    • not-sent: the field value is not sent as a residue.

    • value-sent: the field value is sent in extenso in the residue.

    • LSB: the bits remaining after the MSB comparison are sent in the residue.

    • mapping-sent: the index of the matching element in the array is sent.

    • compute: the field is not sent in the residue and the receiver knows how to recover the value from other information. This is generally used for length and checksum.

  • CDAa: represents the argument of the CDA. Currently, no CDAa is defined.

For example:

{
  "ruleID": 12,
  "ruleLength": 4,
  "compression": [
    {"FID": "IPV6.VER", "FL": 4, "FP": 1, "DI": "Bi", "TV": 6, "MO": "equal", "CDA": "not-sent"},
    {"FID": "IPV6.TC",  "FL": 8, "FP": 1, "DI": "Bi", "TV": 0, "MO": "equal", "CDA": "not-sent"},
    {"FID": "IPV6.FL",  "FL": 20,"FP": 1, "DI": "Bi", "TV": 0, "MO": "ignore","CDA": "not-sent"},
    {"FID": "IPV6.LEN", "FL": 16,"FP": 1, "DI": "Bi",          "MO": "ignore","CDA": "compute-length"},
    {"FID": "IPV6.NXT", "FL": 8, "FP": 1, "DI": "Bi", "TV": 58, "MO": "equal", "CDA": "not-sent"},
    {"FID": "IPV6.HOP_LMT","FL": 8,"FP": 1,"DI": "Bi","TV": 255,"MO": "ignore","CDA": "not-sent"},
    {"FID": "IPV6.DEV_PREFIX","FL": 64,"FP": 1,"DI": "Bi","TV": ["2001:db8::/64",
                                                                 "fe80::/64",
                                                                 "2001:0420:c0dc:1002::/64" ],
                                                                "MO": "match-mapping","CDA": "mapping-sent","SB": 1},
    {"FID": "IPV6.DEV_IID","FL": 64,"FP": 1,"DI": "Bi","TV": "::79","MO": "equal","CDA": "DEVIID"},
    {"FID": "IPV6.APP_PREFIX","FL": 64,"FP": 1,"DI": "Bi","TV": [ "2001:db8:1::/64",
                                                                  "fe80::/64",
                                                                  "2404:6800:4004:818::/64" ],
                                                                "MO": "match-mapping","CDA": "mapping-sent", "SB": 2},
    {"FID": "IPV6.APP_IID","FL": 64,"FP": 1,"DI": "Bi","TV": "::2004","MO": "equal","CDA": "not-sent"},
    {"FID": "ICMPV6.TYPE","FL": 8,"FP": 1,"DI": "Bi","TV": 128,"MO": "equal","CDA": "not-sent"},
    {"FID": "ICMPV6.CODE","FL": 8,"FP": 1,"DI": "Bi","TV": 0,  "MO": "equal","CDA": "not-sent"},
    {"FID": "ICMPV6.CKSUM","FL": 16,"FP": 1,"DI": "Bi","TV": 0,"MO": "ignore","CDA": "compute-checksum"},
    {"FID": "ICMPV6.IDENT","FL": 16,"FP": 1,"DI": "Bi","TV": [],"MO": "ignore","CDA": "value-sent"},
    {"FID": "ICMPV6.SEQNB","FL": 16,"FP": 1,"DI": "Bi","TV": [],"MO": "ignore","CDA": "value-sent"}
  ]
}

Fragmentation Rules

Fragmentation rules define how the compression and decompression must be performed.

The keyword Fragmentation is followed by a dictionnary containing the different parameters used. Inside the keyword FRMode indicates which Fragmentation mode is used (noAck, ackAlways, ackOnError). FRDirection give the direction of the fragmentation rule. UP means that data fragments are sent by the device, DW for the opposite direction. This entry is mandatory. Then the keyword FRModeProfiler gives the information needed to create the SCHC fragmentation header and mode profile:

  • dtagSize gives in bit the size of the dtag field. <<if not present or set to 0, this field is not present in the SCHC fragmentation header>>. This keyword can be used by all the fragmentation modes.

  • WSize gives in bit the size of Window field. If not present, the default value is 0 (no window) in noAck and 1 in ackAlways. In ackOnErr this field must be set to 1 or to an higher value.

  • FCNSize gives in bit the size of the FCN field. If not present, by default, the value is 1 for noAck.For ackAlways and ackOnError the value must be specified.

  • ackBehavior this keyword specifies on ackOnError, when the fragmenter except to receive a bitmap from the reassembler:

    • afterAll1: the bitmap (or RCS OK) is expected only after the reception of a All-1.

    • afterAll0: the bitmap may be expected after the transmission of the window last fragment (All-0 or All-1)

  • lastTileInAll1: true to append last tile to the All-1 message, false otherwise.

  • tileSize gives the size in bit of a tile.

  • MICAlgorithm gives the algorithm used to compute the MIB, by default crc32,

  • MICWordSize gives the size of the RCS word.

  • maxRetry indicates to the sender how many time a fragment or ack request can be sent.

  • timeout indicated in seconds to the sender how many time between two retransmissions. The receiver can compute the delay before aborting.

For instance:

{
    "RuleID": 1,
    "RuleLength": 3,
    "Fragmentation" : {
        "FRMode": "ackOnError",
        "FRDirection": "UP",
        "FRModeProfile": {
            "dtagSize": 2,
            "WSize": 5,
            "FCNSize": 3,
            "ackBehavior": "afterAll1",
            "tileSize": 9,
            "MICAlgorithm": "crc32",
            "MICWordSize": 8,
            "maxRetry": 4,
            "timeout": 600,
            "lastTileInAll1": false
        }
    }
}

Context

A context is associated with a specific device, which may be identified by a unique LPWAN identifier, for instance a LoRaWAN devEUI.

The context also includes a set of rules. The rule description is defined [above](#rule-definition):

[
    {
        "DeviceID": 0x1234567890,
        "SoR" : [ ..... ]
    },
    {
        "DeviceID": 0xDEADBEEF,
        "SoR" : [ ..... ]
    },
    ...
]

DeviceID is a numerical value that must be unique in the context. If the context is used on a device, the deviceID may be omitted or set to null. In the core network, the DeviceIDs must be specified.

The set of rules itself expands as shown below:

[
    {
    "RuleID" : 12,
    "RuleIDLength" : 4,
    "compression": [
        {
        "FID": "IPV6.VER",
        "FL": 4,
        "FP": 1,
        "DI": "Bi",
        "TV": 6,
        "MO": "equal",
        "CDA": "not-sent"
        },
        {
        "FID": "IPV6.DEV_PREFIX",
        "FL": 64,
        "FP": 1,
        "DI": "Bi",
        "TV": [ "2001:db8::/64", "fe80::/64", "2001:0420:c0dc:1002::/64" ],
        "MO": "match-mapping",
        "CDA": "mapping-sent",
        },
      ]
    },
    {
    "RuleID" : 13,
    "RuleIDLength" : 4,
    "fragmentation" : ....
    },
    .....
]

Remove

Suppresses a rule for a specific device <<< only one, or a set of rules? >>>. If no rule is specified, all rules for that device are removed from the context:

RM.remove ({"DeviceID": 0x1234567, "SoR": {{"ruleID":12, "ruleLength":4}}})
RM.remove ({"DeviceID": 0x1234567})

FindRuleFromPacket

This method returns a rule and a DeviceID that match a packet description given by the protocol analyzer.

FindFragmentationRule (size)

Returns a fragmentation rule compatible with the packet size passed as parameter.

FindRuleFromID

Given the first bits received from the LPWAN, returns either a fragmentation or a compression rule.

class gen_rulemanager.DictToAttrDeep(**entries)
get(k, d=None)

this.get(k)

class gen_rulemanager.RuleManager(file=None, log=None)

# Class RuleManager

A RuleManager object is created this way:

from RuleManager import *

RM = RuleManager()

arguments:

  • file: the RuleManager takes a file to upload rule_set

  • log: display debugging events

Add(device=None, dev_info=None, file=None, compression=True)

Add is used to add a new rule or a set of rules to a context. Add checks the validity of the rule:

  • ruleID/RuleIDLength do not overlap

  • the rule contains either one of a fragmentation and a compression description.

If the DeviceID already exists in the context, the new rule is added to that context, providing no conflict on the RuleID is found.

RM.Add ({“DeviceID”: 0x1234567, “sor”: {…..}})

FindFragmentationRule(deviceID=None, originalSize=None, reliability='NoAck', direction='UP', packet=None)

Lookup a fragmentation rule.

Find a fragmentation rule regarding parameters: * original SCHC packet size * reliability NoAck, AckOnError, AckAlways * direction (UP or DOWN) NOTE: Not yet implemented, returns the first fragmentation rule.

XXX please check whether the following strategy is okey. - if direction is specified, and deviceID is None, it is assumed that

the request is for a device. Return the 1st rule matched with the direction regardless of the deviceID. A deviceID for a device is not configured typically.

  • if raw_packet is not None, it compares the rule_id with the packet.

  • if the direction and the deviceID is matched.

FindRuleFromPacket(pkt, direction='BI', failed_field=False)

Takes a parsed packet and returns the matching rule.

FindRuleFromSCHCpacket(schc, device=None)

returns the rule corresponding to the id stored at the beginning of the SCHC packet.

Print()

Print a context

add_context(context, comp=None, fragSender=None, fragReceiver=None)

add context into the db.

add_rule(context, key, rule)

Check rule integrity and uniqueless and add it to the db

add_rules(context, comp=None, fragSender=None, fragReceiver=None)

add rules into the context specified.

check_rule_compression(rule)

compression rule check

check_rule_fragmentation(rule)

fragmentation rule check

find_context_bydstiid(dst_iid)

find a context with dst_iid, which can be a wild card.

find_context_exact(dev_L2addr, dst_iid)

find a context by both devL2Addr and dstIID. This is mainly for internal use.

find_rule_bypacket(context, packet_bbuf)

returns a compression rule or an fragmentation rule in the context matching with the field value of rule id in the packet.

to_yang(format='json')

Print a context