rule2sor 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rule2sor-0.1.0/.gitignore +6 -0
- rule2sor-0.1.0/.vscode/launch.json +29 -0
- rule2sor-0.1.0/LICENSE +21 -0
- rule2sor-0.1.0/PKG-INFO +65 -0
- rule2sor-0.1.0/README.md +51 -0
- rule2sor-0.1.0/pyproject.toml +22 -0
- rule2sor-0.1.0/rule2sor/__init__.py +3 -0
- rule2sor-0.1.0/rule2sor/cli.py +80 -0
- rule2sor-0.1.0/rule2sor/gen_parameters.py +318 -0
- rule2sor-0.1.0/rule2sor/gen_rulemanager.py +1061 -0
- rule2sor-0.1.0/rule2sor/ietf-schc@2026-05-07.sid +939 -0
- rule2sor-0.1.0/uv.lock +301 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.2.0",
|
|
3
|
+
"configurations": [
|
|
4
|
+
{
|
|
5
|
+
"name": "Debug rule2sor (inner.json)",
|
|
6
|
+
"type": "debugpy",
|
|
7
|
+
"request": "launch",
|
|
8
|
+
"module": "rule2sor.cli",
|
|
9
|
+
"python": "${workspaceFolder}/.venv/bin/python",
|
|
10
|
+
"args": [
|
|
11
|
+
"${workspaceFolder}/../oscore/inner.json"
|
|
12
|
+
],
|
|
13
|
+
"cwd": "${workspaceFolder}",
|
|
14
|
+
"console": "integratedTerminal"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"name": "Debug rule2sor (active file)",
|
|
18
|
+
"type": "debugpy",
|
|
19
|
+
"request": "launch",
|
|
20
|
+
"module": "rule2sor.cli",
|
|
21
|
+
"python": "${workspaceFolder}/.venv/bin/python",
|
|
22
|
+
"args": [
|
|
23
|
+
"${file}"
|
|
24
|
+
],
|
|
25
|
+
"cwd": "${workspaceFolder}",
|
|
26
|
+
"console": "integratedTerminal"
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
rule2sor-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Laurent Toutain
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
rule2sor-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rule2sor
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Convert OpenSCHC JSON rule files into CORECONF/CBOR .sor files
|
|
5
|
+
Project-URL: Homepage, https://github.com/ltn22/rule2sor
|
|
6
|
+
Author-email: Laurent Toutain <laurent.toutain@gmail.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Python: >=3.9
|
|
10
|
+
Requires-Dist: cbor-diag
|
|
11
|
+
Requires-Dist: cbor2
|
|
12
|
+
Requires-Dist: pycoreconf>=0.3
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# rule2sor
|
|
16
|
+
|
|
17
|
+
Convert [OpenSCHC](https://github.com/ltn22/openschc) JSON rule files into
|
|
18
|
+
`.sor` files (the Set of Rules serialized in CORECONF/CBOR, following the
|
|
19
|
+
ietf-schc YANG data model).
|
|
20
|
+
|
|
21
|
+
## Usage with uvx
|
|
22
|
+
|
|
23
|
+
uvx --from git+https://github.com/ltn22/rule2sor rule2sor <rule-file.json>
|
|
24
|
+
|
|
25
|
+
Or after installation (`pip install git+https://github.com/ltn22/rule2sor`):
|
|
26
|
+
|
|
27
|
+
rule2sor <rule-file.json> [-s <sid-file>] [-o <output.sor>] [-q]
|
|
28
|
+
|
|
29
|
+
By default the output file has the same name as the input with the `.sor`
|
|
30
|
+
extension, and the SID file is the bundled `ietf-schc@2026-05-07.sid`.
|
|
31
|
+
With `-q` only the final message is printed.
|
|
32
|
+
|
|
33
|
+
If you pass a `.sor` file instead of a JSON file, `rule2sor` will read and print
|
|
34
|
+
its contents (CBOR hex, CBOR diagnostic notation, and decoded RESTCONF JSON)
|
|
35
|
+
directly to the standard output:
|
|
36
|
+
|
|
37
|
+
rule2sor <file.sor> [-s <sid-file>]
|
|
38
|
+
|
|
39
|
+
Example:
|
|
40
|
+
|
|
41
|
+
rule2sor atmos41.json
|
|
42
|
+
# -> atmos41.sor
|
|
43
|
+
|
|
44
|
+
rule2sor atmos41.sor
|
|
45
|
+
# displays the content of atmos41.sor
|
|
46
|
+
|
|
47
|
+
## What it does
|
|
48
|
+
|
|
49
|
+
This is an extraction of the minimal code from OpenSCHC:
|
|
50
|
+
|
|
51
|
+
- `gen_rulemanager.py` — trimmed `RuleManager` keeping:
|
|
52
|
+
- `Add()`: loads a JSON rule file, checks rule integrity (RuleID overlaps,
|
|
53
|
+
valid FID/MO/CDA, one of compression/fragmentation/no-compression per
|
|
54
|
+
rule) and fills in missing defaults (FL, FP, DI);
|
|
55
|
+
- `Print()`: displays the rules as ASCII tables;
|
|
56
|
+
- `add_sid_file()` / `to_coreconf()`: serializes the Set of Rules in
|
|
57
|
+
CORECONF/CBOR using the SID values.
|
|
58
|
+
- `gen_parameters.py` — constants, `YANG_ID` mapping (simplified to a direct
|
|
59
|
+
name-to-YANG-identifier mapping) and `adapt_value()`.
|
|
60
|
+
- `ietf-schc@2026-05-07.sid` — default SID file.
|
|
61
|
+
|
|
62
|
+
## JSON rule format
|
|
63
|
+
|
|
64
|
+
See the long docstring at the top of `rule2sor/gen_rulemanager.py`, which
|
|
65
|
+
documents the OpenSCHC JSON rule data model (compression and fragmentation).
|
rule2sor-0.1.0/README.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# rule2sor
|
|
2
|
+
|
|
3
|
+
Convert [OpenSCHC](https://github.com/ltn22/openschc) JSON rule files into
|
|
4
|
+
`.sor` files (the Set of Rules serialized in CORECONF/CBOR, following the
|
|
5
|
+
ietf-schc YANG data model).
|
|
6
|
+
|
|
7
|
+
## Usage with uvx
|
|
8
|
+
|
|
9
|
+
uvx --from git+https://github.com/ltn22/rule2sor rule2sor <rule-file.json>
|
|
10
|
+
|
|
11
|
+
Or after installation (`pip install git+https://github.com/ltn22/rule2sor`):
|
|
12
|
+
|
|
13
|
+
rule2sor <rule-file.json> [-s <sid-file>] [-o <output.sor>] [-q]
|
|
14
|
+
|
|
15
|
+
By default the output file has the same name as the input with the `.sor`
|
|
16
|
+
extension, and the SID file is the bundled `ietf-schc@2026-05-07.sid`.
|
|
17
|
+
With `-q` only the final message is printed.
|
|
18
|
+
|
|
19
|
+
If you pass a `.sor` file instead of a JSON file, `rule2sor` will read and print
|
|
20
|
+
its contents (CBOR hex, CBOR diagnostic notation, and decoded RESTCONF JSON)
|
|
21
|
+
directly to the standard output:
|
|
22
|
+
|
|
23
|
+
rule2sor <file.sor> [-s <sid-file>]
|
|
24
|
+
|
|
25
|
+
Example:
|
|
26
|
+
|
|
27
|
+
rule2sor atmos41.json
|
|
28
|
+
# -> atmos41.sor
|
|
29
|
+
|
|
30
|
+
rule2sor atmos41.sor
|
|
31
|
+
# displays the content of atmos41.sor
|
|
32
|
+
|
|
33
|
+
## What it does
|
|
34
|
+
|
|
35
|
+
This is an extraction of the minimal code from OpenSCHC:
|
|
36
|
+
|
|
37
|
+
- `gen_rulemanager.py` — trimmed `RuleManager` keeping:
|
|
38
|
+
- `Add()`: loads a JSON rule file, checks rule integrity (RuleID overlaps,
|
|
39
|
+
valid FID/MO/CDA, one of compression/fragmentation/no-compression per
|
|
40
|
+
rule) and fills in missing defaults (FL, FP, DI);
|
|
41
|
+
- `Print()`: displays the rules as ASCII tables;
|
|
42
|
+
- `add_sid_file()` / `to_coreconf()`: serializes the Set of Rules in
|
|
43
|
+
CORECONF/CBOR using the SID values.
|
|
44
|
+
- `gen_parameters.py` — constants, `YANG_ID` mapping (simplified to a direct
|
|
45
|
+
name-to-YANG-identifier mapping) and `adapt_value()`.
|
|
46
|
+
- `ietf-schc@2026-05-07.sid` — default SID file.
|
|
47
|
+
|
|
48
|
+
## JSON rule format
|
|
49
|
+
|
|
50
|
+
See the long docstring at the top of `rule2sor/gen_rulemanager.py`, which
|
|
51
|
+
documents the OpenSCHC JSON rule data model (compression and fragmentation).
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "rule2sor"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Convert OpenSCHC JSON rule files into CORECONF/CBOR .sor files"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Laurent Toutain", email = "laurent.toutain@gmail.com" }]
|
|
13
|
+
dependencies = ["cbor2", "cbor-diag", "pycoreconf>=0.3"]
|
|
14
|
+
|
|
15
|
+
[project.urls]
|
|
16
|
+
Homepage = "https://github.com/ltn22/rule2sor"
|
|
17
|
+
|
|
18
|
+
[project.scripts]
|
|
19
|
+
rule2sor = "rule2sor.cli:main"
|
|
20
|
+
|
|
21
|
+
[tool.hatch.build.targets.wheel]
|
|
22
|
+
packages = ["rule2sor"]
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
rule2sor: convert an OpenSCHC JSON rule file into a .sor file
|
|
4
|
+
(CORECONF/CBOR representation of the Set of Rules).
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
rule2sor <rule-file.json> [-s <sid-file>] [-o <output.sor>] [-q]
|
|
8
|
+
|
|
9
|
+
The rules are validated and completed by RuleManager.Add(), then
|
|
10
|
+
serialized with RuleManager.to_coreconf().
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import argparse
|
|
14
|
+
import binascii
|
|
15
|
+
import json
|
|
16
|
+
import os
|
|
17
|
+
import sys
|
|
18
|
+
|
|
19
|
+
from cbor_diag import cbor2diag
|
|
20
|
+
from pycoreconf import CORECONFModel
|
|
21
|
+
|
|
22
|
+
from .gen_rulemanager import RuleManager
|
|
23
|
+
|
|
24
|
+
DEFAULT_SID_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
|
25
|
+
"ietf-schc@2026-05-07.sid")
|
|
26
|
+
|
|
27
|
+
def main():
|
|
28
|
+
parser = argparse.ArgumentParser(
|
|
29
|
+
description="Convert OpenSCHC JSON rules to a CORECONF/CBOR .sor file, or display a .sor file")
|
|
30
|
+
parser.add_argument("rule_file", help="JSON file describing the set of rules, or .sor file to display")
|
|
31
|
+
parser.add_argument("-s", "--sid", default=DEFAULT_SID_FILE,
|
|
32
|
+
help="SID file (default: %(default)s)")
|
|
33
|
+
parser.add_argument("-o", "--output",
|
|
34
|
+
help="output .sor file (default: rule file with .sor extension)")
|
|
35
|
+
parser.add_argument("-q", "--quiet", action="store_true",
|
|
36
|
+
help="do not print the rules nor the CBOR dump")
|
|
37
|
+
args = parser.parse_args()
|
|
38
|
+
|
|
39
|
+
if args.rule_file.endswith(".sor"):
|
|
40
|
+
if not os.path.exists(args.rule_file):
|
|
41
|
+
print(f"Error: file not found: {args.rule_file}", file=sys.stderr)
|
|
42
|
+
sys.exit(1)
|
|
43
|
+
with open(args.rule_file, "rb") as f:
|
|
44
|
+
ycbor = f.read()
|
|
45
|
+
print("CBOR (hex):", binascii.hexlify(ycbor).decode())
|
|
46
|
+
print("\nCBOR diagnostic notation:")
|
|
47
|
+
print(cbor2diag(ycbor))
|
|
48
|
+
print("\nRESTCONF JSON:")
|
|
49
|
+
model = CORECONFModel([args.sid])
|
|
50
|
+
print(json.dumps(model.decode(ycbor, as_rfc7951=True), indent=2))
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
output = args.output
|
|
54
|
+
if output is None:
|
|
55
|
+
base, _ = os.path.splitext(args.rule_file)
|
|
56
|
+
output = base + ".sor"
|
|
57
|
+
|
|
58
|
+
rm = RuleManager()
|
|
59
|
+
rm.Add(file=args.rule_file, device="test:device1")
|
|
60
|
+
rm.add_sid_file(args.sid)
|
|
61
|
+
|
|
62
|
+
if not args.quiet:
|
|
63
|
+
rm.Print()
|
|
64
|
+
|
|
65
|
+
ycbor = rm.to_coreconf()
|
|
66
|
+
if not args.quiet:
|
|
67
|
+
print(binascii.hexlify(ycbor))
|
|
68
|
+
print("\nCBOR diagnostic notation:")
|
|
69
|
+
print(cbor2diag(ycbor))
|
|
70
|
+
print("\nRESTCONF JSON:")
|
|
71
|
+
model = CORECONFModel([args.sid])
|
|
72
|
+
print(json.dumps(model.decode(ycbor, as_rfc7951=True), indent=2))
|
|
73
|
+
|
|
74
|
+
with open(output, "wb") as f:
|
|
75
|
+
f.write(ycbor)
|
|
76
|
+
|
|
77
|
+
print("{} written ({} bytes)".format(output, len(ycbor)))
|
|
78
|
+
|
|
79
|
+
if __name__ == "__main__":
|
|
80
|
+
sys.exit(main())
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
T_RULEID = "RuleID"
|
|
2
|
+
T_RULEIDVALUE = "RuleIDValue"
|
|
3
|
+
T_RULEIDLENGTH = "RuleIDLength"
|
|
4
|
+
T_DEVICEID = "DeviceID"
|
|
5
|
+
|
|
6
|
+
T_FID = "FID"
|
|
7
|
+
T_FL = "FL"
|
|
8
|
+
T_FP = "FP"
|
|
9
|
+
T_DI = "DI"
|
|
10
|
+
T_TV = "TV"
|
|
11
|
+
T_TV_IND = "TV.IND"
|
|
12
|
+
T_MO = "MO"
|
|
13
|
+
T_MO_VAL = "MO.VAL"
|
|
14
|
+
T_CDA = "CDA"
|
|
15
|
+
T_SB = "SB"
|
|
16
|
+
|
|
17
|
+
T_PROTO_IPV6 = "IPV6"
|
|
18
|
+
# IPv6 header fields
|
|
19
|
+
T_IPV6_VER = "IPV6.VER"
|
|
20
|
+
T_IPV6_TC = "IPV6.TC"
|
|
21
|
+
T_IPV6_FL = "IPV6.FL"
|
|
22
|
+
T_IPV6_LEN = "IPV6.LEN"
|
|
23
|
+
T_IPV6_NXT = "IPV6.NXT"
|
|
24
|
+
T_IPV6_HOP_LMT = "IPV6.HOP_LMT"
|
|
25
|
+
T_IPV6_DEV_PREFIX = "IPV6.DEV_PREFIX"
|
|
26
|
+
T_IPV6_DEV_IID = "IPV6.DEV_IID"
|
|
27
|
+
T_IPV6_APP_PREFIX = "IPV6.APP_PREFIX"
|
|
28
|
+
T_IPV6_APP_IID = "IPV6.APP_IID"
|
|
29
|
+
|
|
30
|
+
T_IPV4_VER = "IPV4.VER"
|
|
31
|
+
|
|
32
|
+
T_PROTO_ICMPV6 = "ICMPV6"
|
|
33
|
+
# ICMPv6 header fields
|
|
34
|
+
T_ICMPV6_TYPE = "ICMPV6.TYPE"
|
|
35
|
+
T_ICMPV6_CODE = "ICMPV6.CODE"
|
|
36
|
+
T_ICMPV6_CKSUM = "ICMPV6.CKSUM"
|
|
37
|
+
T_ICMPV6_IDENT = "ICMPV6.IDENT"
|
|
38
|
+
T_ICMPV6_SEQNO = "ICMPV6.SEQNO"
|
|
39
|
+
T_ICMPV6_UNUSED = "ICMPV6.UNUSED"
|
|
40
|
+
T_ICMPV6_PAYLOAD = "ICMPV6.PAYLOAD"
|
|
41
|
+
# ICMPv6 types
|
|
42
|
+
T_ICMPV6_TYPE_ECHO_REQUEST = "ICMPV6.TYPE.ECHO.REQUEST"
|
|
43
|
+
T_ICMPV6_TYPE_ECHO_REPLY = "ICMPV6.TYPE.ECHO.REPLY"
|
|
44
|
+
|
|
45
|
+
T_PROTO_UDP = "UDP"
|
|
46
|
+
# UDP fields
|
|
47
|
+
T_UDP_DEV_PORT = "UDP.DEV_PORT"
|
|
48
|
+
T_UDP_APP_PORT = "UDP.APP_PORT"
|
|
49
|
+
T_UDP_LEN = "UDP.LEN"
|
|
50
|
+
T_UDP_CKSUM = "UDP.CKSUM"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
T_PROTO_COAP = "COAP"
|
|
55
|
+
# CoAP fields
|
|
56
|
+
T_COAP_VERSION = "COAP.VER"
|
|
57
|
+
T_COAP_TYPE = "COAP.TYPE"
|
|
58
|
+
T_COAP_TKL = "COAP.TKL"
|
|
59
|
+
T_COAP_CODE = "COAP.CODE"
|
|
60
|
+
T_COAP_MID = "COAP.MID"
|
|
61
|
+
T_COAP_TOKEN = "COAP.TOKEN"
|
|
62
|
+
# CoAP options string (written exactly as in standards)
|
|
63
|
+
T_COAP_OPT_IF_MATCH = "COAP.IF-MATCH"
|
|
64
|
+
T_COAP_OPT_URI_HOST = "COAP.URI-HOST"
|
|
65
|
+
T_COAP_OPT_ETAG = "COAP.ETAG"
|
|
66
|
+
T_COAP_OPT_IF_NONE_MATCH = "COAP.IF-NONE-MATCH"
|
|
67
|
+
T_COAP_OPT_OBS = "COAP.OBSERVE"
|
|
68
|
+
T_COAP_OPT_URI_PORT = "COAP.URI-PORT"
|
|
69
|
+
T_COAP_OPT_LOC_PATH = "COAP.LOCATION-PATH"
|
|
70
|
+
T_COAP_OPT_URI_PATH = "COAP.URI-PATH"
|
|
71
|
+
T_COAP_OPT_CONT_FORMAT = "COAP.CONTENT-FORMAT"
|
|
72
|
+
T_COAP_OPT_MAX_AGE = "COAP.MAX-AGE"
|
|
73
|
+
T_COAP_OPT_URI_QUERY = "COAP.URI-QUERY"
|
|
74
|
+
T_COAP_OPT_ACCEPT = "COAP.ACCEPT"
|
|
75
|
+
T_COAP_OPT_LOC_QUERY = "COAP.LOCATION-QUERY"
|
|
76
|
+
T_COAP_OPT_BLOCK2 = "COAP.BLOCK2"
|
|
77
|
+
T_COAP_OPT_BLOCK1 = "COAP.BLOCK1"
|
|
78
|
+
T_COAP_OPT_SIZE2 = "COAP.SIZE2"
|
|
79
|
+
T_COAP_OPT_PROXY_URI = "COAP.PROXY-URI"
|
|
80
|
+
T_COAP_OPT_PROXY_SCHEME = "COAP.PROXY-SCHEME"
|
|
81
|
+
T_COAP_OPT_SIZE1 = "COAP.SIZE1"
|
|
82
|
+
T_COAP_OPT_NO_RESP = "COAP.NO-RESPONSE"
|
|
83
|
+
|
|
84
|
+
T_OSCORE_FLAGS = "COAP.OSCORE_FLAGS"
|
|
85
|
+
T_OSCORE_FLAGS_FLAGS = "COAP.OSCORE_FLAGS_FLAGS"
|
|
86
|
+
T_OSCORE_FLAGS_N = "COAP.OSCORE_FLAGS_N"
|
|
87
|
+
T_OSCORE_KID = "COAP.OSCORE_KID"
|
|
88
|
+
T_OSCORE_KIDCTX = "COAP.OSCORE_KID_CTX"
|
|
89
|
+
T_OSCORE_PIV = "COAP.OSCORE_PIV"
|
|
90
|
+
T_COAP_OPT_END = "COAP.End"
|
|
91
|
+
|
|
92
|
+
T_UNUSED = "UNUSED"
|
|
93
|
+
T_PAYLOAD = "PAYLOAD"
|
|
94
|
+
|
|
95
|
+
T_FUNCTION_VAR = "var"
|
|
96
|
+
T_FUNCTION_TKL = "tkl"
|
|
97
|
+
|
|
98
|
+
T_FUNCTION_VAR = "var"
|
|
99
|
+
T_FUNCTION_VARBIT = "var_bit"
|
|
100
|
+
T_FUNCTION_TKL = "tkl"
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
T_DIR_UP = "UP"
|
|
104
|
+
T_DIR_DW = "DW"
|
|
105
|
+
T_DIR_BI = "BI"
|
|
106
|
+
|
|
107
|
+
T_MO_EQUAL = "EQUAL"
|
|
108
|
+
T_MO_IGNORE = "IGNORE"
|
|
109
|
+
T_MO_MSB = "MSB"
|
|
110
|
+
T_MO_MMAP = "MATCH-MAPPING"
|
|
111
|
+
T_MO_MATCH_REV_RULE = "REV-RULE-MATCH"
|
|
112
|
+
|
|
113
|
+
T_CDA_NOT_SENT = "NOT-SENT"
|
|
114
|
+
T_CDA_VAL_SENT = "VALUE-SENT"
|
|
115
|
+
T_CDA_MAP_SENT = "MAPPING-SENT"
|
|
116
|
+
T_CDA_LSB = "LSB"
|
|
117
|
+
T_CDA_COMP_LEN = "COMPUTE-LENGTH"
|
|
118
|
+
T_CDA_COMP_CKSUM = "COMPUTE-CHECKSUM"
|
|
119
|
+
T_CDA_DEVIID = "DEVIID"
|
|
120
|
+
T_CDA_APPIID = "APPIID"
|
|
121
|
+
T_CDA_LORA_DEVIID = "COMPUTE-DEVIID"
|
|
122
|
+
T_CDA_REV_COMPRESS = "REV-COMPRESSED-SENT"
|
|
123
|
+
|
|
124
|
+
T_ALGO = "ALGO"
|
|
125
|
+
T_ALGO_DIRECT = "DIRECT"
|
|
126
|
+
T_ALGO_COAP_OPT = "COAP_OPTION"
|
|
127
|
+
|
|
128
|
+
T_META = "META"
|
|
129
|
+
T_UP_RULES = "UP_RULES"
|
|
130
|
+
T_DW_RULES = "DW_RULES"
|
|
131
|
+
T_LAST_USED = "LAST_USED"
|
|
132
|
+
|
|
133
|
+
T_ACTION = "Action"
|
|
134
|
+
|
|
135
|
+
T_COMP = "Compression"
|
|
136
|
+
T_NO_COMP = "NoCompression"
|
|
137
|
+
T_FRAG = "Fragmentation"
|
|
138
|
+
T_FRAG_MODE = "FRMode"
|
|
139
|
+
T_FRAG_NO_ACK = "NoAck" #YANG no-ack
|
|
140
|
+
T_FRAG_ACK_ALWAYS = "AckAlways"
|
|
141
|
+
T_FRAG_ACK_ON_ERROR = "AckOnError"
|
|
142
|
+
T_FRAG_DIRECTION = "FRDirection" #YANG direction
|
|
143
|
+
T_FRAG_PROF = "FRModeProfile"
|
|
144
|
+
T_FRAG_DTAG_SIZE = "dtagSize" #YANG dtag-size
|
|
145
|
+
T_FRAG_W_SIZE = "WSize" #YANG w-size
|
|
146
|
+
T_FRAG_FCN = "FCNSize" #YANG fcn-size
|
|
147
|
+
T_FRAG_WINDOW_SIZE = "windowSize" #YANG window-size
|
|
148
|
+
T_MAX_INTER_FRAME = "MaxInterFrame" #YANG max-interleaved-frames
|
|
149
|
+
T_FRAG_ACK_BEHAVIOR = "ackBehavior" #YANG ack-behavior
|
|
150
|
+
T_FRAG_AFTER_ALL1 = "afterAll1"
|
|
151
|
+
T_FRAG_AFTER_ALL0 = "afterAll0"
|
|
152
|
+
T_FRAG_AFTER_ANY = "afterAny"
|
|
153
|
+
T_FRAG_TILE = "tileSize" #YANG tile-size
|
|
154
|
+
T_FRAG_MIC = "MICALgorithm" #YANG rcs-algorithm
|
|
155
|
+
T_MAX_PACKET_SIZE = "MaxPcktSize" #YANG maximum-packet-size
|
|
156
|
+
T_MAX_INTER_FRAME = "MaxInterFrame" #YANG max-interleaved-frames
|
|
157
|
+
T_FRAG_MAX_RETRY = "maxRetry" #YANG max-ack-requests
|
|
158
|
+
T_FRAG_TIMEOUT = "timeout" #YANG retransmission-timer
|
|
159
|
+
T_FRAG_L2WORDSIZE = "L2WordSize" #YANG l2-word-size
|
|
160
|
+
T_FRAG_LAST_TILE_IN_ALL1 = "lastTileInAll1" #YANG tile-in-all-1
|
|
161
|
+
T_FRAG_RFC8724 = "RCS_CRC32"
|
|
162
|
+
|
|
163
|
+
T_POSITION_CORE = "core"
|
|
164
|
+
T_POSITION_DEVICE = "device"
|
|
165
|
+
|
|
166
|
+
T_INDEXES = "Indexes"
|
|
167
|
+
T_CMD_INDIRECT = "INDIRECT"
|
|
168
|
+
|
|
169
|
+
T_O_DELTA = "COAP.O-DELTA"
|
|
170
|
+
T_O_LENGTH = "COAP.O-LENGTH"
|
|
171
|
+
T_O_VALUE = "COAP.O-VALUE"
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
YANG_ID = {
|
|
175
|
+
"module": "ietf-schc",
|
|
176
|
+
T_CDA_APPIID: "cda-appiid",
|
|
177
|
+
T_CDA_COMP_CKSUM: "cda-compute",
|
|
178
|
+
T_CDA_COMP_LEN: "cda-compute",
|
|
179
|
+
T_CDA_DEVIID: "cda-deviid",
|
|
180
|
+
T_CDA_LSB: "cda-lsb",
|
|
181
|
+
T_CDA_MAP_SENT: "cda-mapping-sent",
|
|
182
|
+
T_CDA_NOT_SENT: "cda-not-sent",
|
|
183
|
+
T_CDA_VAL_SENT: "cda-value-sent",
|
|
184
|
+
T_DIR_BI: "di-bidirectional",
|
|
185
|
+
T_DIR_DW: "di-down",
|
|
186
|
+
T_DIR_UP: "di-up",
|
|
187
|
+
T_COAP_CODE: "fid-coap-code",
|
|
188
|
+
T_COAP_MID: "fid-coap-mid",
|
|
189
|
+
T_OSCORE_FLAGS: "fid-coap-option-oscore-flags",
|
|
190
|
+
T_OSCORE_FLAGS_FLAGS: "fid-coap-option-oscore-flags-flags",
|
|
191
|
+
T_OSCORE_FLAGS_N: "fid-coap-option-oscore-flags-n",
|
|
192
|
+
T_OSCORE_KID: "fid-coap-option-oscore-kid",
|
|
193
|
+
T_OSCORE_KIDCTX: "fid-coap-option-oscore-kidctx",
|
|
194
|
+
T_OSCORE_PIV: "fid-coap-option-oscore-piv",
|
|
195
|
+
T_COAP_TKL: "fid-coap-tkl",
|
|
196
|
+
T_COAP_TOKEN: "fid-coap-token",
|
|
197
|
+
T_COAP_TYPE: "fid-coap-type",
|
|
198
|
+
T_COAP_VERSION: "fid-coap-version",
|
|
199
|
+
T_IPV6_APP_IID: "fid-ipv6-appiid",
|
|
200
|
+
T_IPV6_APP_PREFIX: "fid-ipv6-appprefix",
|
|
201
|
+
T_IPV6_DEV_IID: "fid-ipv6-deviid",
|
|
202
|
+
T_IPV6_DEV_PREFIX: "fid-ipv6-devprefix",
|
|
203
|
+
T_IPV6_FL: "fid-ipv6-flowlabel",
|
|
204
|
+
T_IPV6_HOP_LMT: "fid-ipv6-hoplimit",
|
|
205
|
+
T_IPV6_NXT: "fid-ipv6-nextheader",
|
|
206
|
+
T_IPV6_LEN: "fid-ipv6-payload-length",
|
|
207
|
+
T_IPV6_TC: "fid-ipv6-trafficclass",
|
|
208
|
+
T_IPV6_VER: "fid-ipv6-version",
|
|
209
|
+
T_IPV4_VER: "fid-ipv6-version",
|
|
210
|
+
T_UDP_APP_PORT: "fid-udp-app-port",
|
|
211
|
+
T_UDP_CKSUM: "fid-udp-checksum",
|
|
212
|
+
T_UDP_DEV_PORT: "fid-udp-dev-port",
|
|
213
|
+
T_UDP_LEN: "fid-udp-length",
|
|
214
|
+
T_FUNCTION_TKL: "fl-token-length",
|
|
215
|
+
T_FUNCTION_VAR: "fl-variable",
|
|
216
|
+
T_FUNCTION_VARBIT: "fl-variable-bit",
|
|
217
|
+
T_FRAG_ACK_ALWAYS: "fragmentation-mode-ack-always",
|
|
218
|
+
T_FRAG_ACK_ON_ERROR: "fragmentation-mode-ack-on-error",
|
|
219
|
+
T_FRAG_NO_ACK: "fragmentation-mode-no-ack",
|
|
220
|
+
T_MO_EQUAL: "mo-equal",
|
|
221
|
+
T_MO_IGNORE: "mo-ignore",
|
|
222
|
+
T_MO_MMAP: "mo-match-mapping",
|
|
223
|
+
T_MO_MSB: "mo-msb",
|
|
224
|
+
T_FRAG_RFC8724: "rcs-crc32",
|
|
225
|
+
# from OAM
|
|
226
|
+
T_ICMPV6_CODE: "fid-icmpv6-code",
|
|
227
|
+
T_ICMPV6_TYPE: "fid-icmpv6-type",
|
|
228
|
+
T_ICMPV6_IDENT: "fid-icmpv6-identifier",
|
|
229
|
+
T_ICMPV6_SEQNO: "fid-icmpv6-sequence",
|
|
230
|
+
T_ICMPV6_CKSUM: "fid-icmpv6-checksum",
|
|
231
|
+
T_ICMPV6_PAYLOAD: "fid-icmpv6-payload",
|
|
232
|
+
# for quentin extension
|
|
233
|
+
T_O_DELTA: "fid-coap-delta-types",
|
|
234
|
+
T_O_LENGTH: "fid-coap-length",
|
|
235
|
+
T_O_VALUE: "fid-coap-value",
|
|
236
|
+
|
|
237
|
+
T_UNUSED: "fid-unused",
|
|
238
|
+
T_PAYLOAD: "fid-payload",
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
COAP_OPTION_NUMBERS = {
|
|
242
|
+
T_COAP_OPT_IF_MATCH: 1,
|
|
243
|
+
T_COAP_OPT_URI_HOST: 3,
|
|
244
|
+
T_COAP_OPT_ETAG: 4,
|
|
245
|
+
T_COAP_OPT_IF_NONE_MATCH: 5,
|
|
246
|
+
T_COAP_OPT_OBS: 6,
|
|
247
|
+
T_COAP_OPT_URI_PORT: 7,
|
|
248
|
+
T_COAP_OPT_LOC_PATH: 8,
|
|
249
|
+
T_COAP_OPT_URI_PATH: 11,
|
|
250
|
+
T_COAP_OPT_CONT_FORMAT: 12,
|
|
251
|
+
T_COAP_OPT_MAX_AGE: 14,
|
|
252
|
+
T_COAP_OPT_URI_QUERY: 15,
|
|
253
|
+
T_COAP_OPT_ACCEPT: 17,
|
|
254
|
+
T_COAP_OPT_LOC_QUERY: 20,
|
|
255
|
+
T_COAP_OPT_BLOCK2: 23,
|
|
256
|
+
T_COAP_OPT_BLOCK1: 27,
|
|
257
|
+
T_COAP_OPT_SIZE2: 28,
|
|
258
|
+
T_COAP_OPT_PROXY_URI: 35,
|
|
259
|
+
T_COAP_OPT_PROXY_SCHEME: 39,
|
|
260
|
+
T_COAP_OPT_SIZE1: 60,
|
|
261
|
+
T_COAP_OPT_NO_RESP: 258,
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
import ipaddress
|
|
265
|
+
|
|
266
|
+
def adapt_value(value, length=None, FID=None):
|
|
267
|
+
"""transform any value of any type in the smallest bytearray.
|
|
268
|
+
FID allows to convert properly the string to IPv6 address."""
|
|
269
|
+
|
|
270
|
+
if type(value) is list:
|
|
271
|
+
result = []
|
|
272
|
+
for e in value:
|
|
273
|
+
result.append(adapt_value(e, length, FID))
|
|
274
|
+
|
|
275
|
+
return value
|
|
276
|
+
|
|
277
|
+
if type(value) is int:
|
|
278
|
+
|
|
279
|
+
if FID in [T_IPV6_APP_IID, T_IPV6_APP_PREFIX, T_IPV6_DEV_IID, T_IPV6_DEV_PREFIX] and length != None:
|
|
280
|
+
return value.to_bytes(length//8, byteorder='big')
|
|
281
|
+
|
|
282
|
+
size = 0
|
|
283
|
+
v = value
|
|
284
|
+
while v != 0:
|
|
285
|
+
v = v >> 8
|
|
286
|
+
size += 1
|
|
287
|
+
|
|
288
|
+
if size == 0: # when value == 0 store 0
|
|
289
|
+
size=1
|
|
290
|
+
|
|
291
|
+
return value.to_bytes (size, byteorder='big')
|
|
292
|
+
if type(value) is str:
|
|
293
|
+
if FID in [T_IPV6_APP_IID, T_IPV6_APP_PREFIX, T_IPV6_DEV_IID, T_IPV6_DEV_PREFIX]:
|
|
294
|
+
# string has to be converted as IPv6 addresses
|
|
295
|
+
|
|
296
|
+
slash_pos = value.find("/")
|
|
297
|
+
if slash_pos != -1:
|
|
298
|
+
# a prefix is given, remove / to be compatible with ip_address
|
|
299
|
+
value = value[:slash_pos]
|
|
300
|
+
|
|
301
|
+
addr = ipaddress.ip_address(value)
|
|
302
|
+
if addr.version != 6: # expect an IPv6 address
|
|
303
|
+
raise ValueError ("only IPv6 is supported, can not support {}".format(addr.version))
|
|
304
|
+
|
|
305
|
+
if FID in [T_IPV6_DEV_PREFIX, T_IPV6_APP_PREFIX]: #prefix top 8
|
|
306
|
+
return addr.packed[:8]
|
|
307
|
+
elif FID in [T_IPV6_DEV_IID, T_IPV6_APP_IID]: #IID bottom 8
|
|
308
|
+
return addr.packed[8:]
|
|
309
|
+
else:
|
|
310
|
+
raise ValueError ("{} Fid not found".format(FID))
|
|
311
|
+
else: # a regular string
|
|
312
|
+
return value.encode()
|
|
313
|
+
elif type(value) is bytes:
|
|
314
|
+
return value
|
|
315
|
+
elif value == None:
|
|
316
|
+
return None
|
|
317
|
+
else:
|
|
318
|
+
raise ValueError("Unknown type", type(value))
|