aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2020-05-03 17:05:10 +0200
committerHarald Welte <laforge@osmocom.org>2022-01-27 10:53:08 +0100
commit775be483526e906414b1e8fd2b15c0b93d6d346b (patch)
treea8f1d90289ca1b9322fca92b3b4f0d147f939271
parentc3c6ee6c63c714c48e60ac678b80ae0b4afedbdc (diff)
WIP: LAPDlaforge/lapd
-rw-r--r--lapd/LAPD_Primitives.ttcn112
-rw-r--r--lapd/LAPD_Tests.ttcn17
-rw-r--r--lapd/RLAPD_CodecPort.ttcn64
-rw-r--r--lapd/RLAPD_CodecPort_CtrlFunct.ttcn52
-rw-r--r--lapd/RLAPD_CodecPort_CtrlFunctDef.cc66
-rwxr-xr-xlapd/gen_links.sh23
-rwxr-xr-xlapd/regen_makefile.sh6
-rw-r--r--library/LAPD_Types.ttcn413
8 files changed, 753 insertions, 0 deletions
diff --git a/lapd/LAPD_Primitives.ttcn b/lapd/LAPD_Primitives.ttcn
new file mode 100644
index 00000000..e6c8f360
--- /dev/null
+++ b/lapd/LAPD_Primitives.ttcn
@@ -0,0 +1,112 @@
+module LAPD_Primitives {
+
+import from LAPD_Types all;
+
+type enumerated PrimOperation {
+ REQUEST,
+ RESPONSE,
+ INDICATION,
+ CONFIRM
+};
+
+type record LAPD_DL_Prim {
+ LapdTei tei,
+ LapdSapi sapi,
+ LAPD_DL primitive,
+ PrimOperation operation
+}
+type union LAPD_DL {
+ LapdDlEstablish dl_establish,
+ LapdDlRelease dl_release,
+ LapdDlData dl_data,
+ LapdDlUnitData dl_unitdata
+};
+type record LapdDlEstablish {
+};
+type record LapdDlRelease {
+};
+type record LapdDlData {
+ octetstring payload
+};
+type record LapdDlUnitData {
+ octetstring payload
+};
+
+type record LAPD_MDL_Prim {
+ LAPD_MDL primitive,
+ PrimOperation operation
+}
+type union LAPD_MDL {
+ LapdMdlAssign mdl_assign,
+ LapdMdlRemove mdl_remove,
+ LapdMdlError mdl_error,
+ LapdMdlUnitData mdl_unitdata,
+ LapdMdlXid mdl_xid
+};
+type record LapdMdlAssign {
+ LapdTei tei
+ //ces
+};
+type record LapdMdlRemove {
+ LapdTei tei
+ //ces
+};
+type record LapdMdlError {
+ charstring reason
+};
+type record LapdMdlUnitData {
+ octetstring lm_pdu
+};
+type record LapdMdlXid {
+ octetstring cm_pdu
+};
+
+type record LAPD_PH_Prim {
+ LAPD_PH primitive,
+ PrimOperation operation
+}
+type union LAPD_PH {
+ LapdPhData ph_data,
+ LapdPhActivate ph_activate,
+ LapdPhDeactivate ph_deactivate
+};
+type record LapdPhData {
+ // priority
+ octetstring data
+};
+type record LapdPhActivate {
+}
+type record LapdPhDeactivate {
+}
+
+type record LAPD_MPH_Prim {
+ Lapd_MPH primitive,
+ PrimOperation operation
+};
+type union Lapd_MPH {
+ LapdMphActivate mph_activate,
+ LapdMphDeactivate mph_deactivate,
+ LapdMphInformation mph_information
+};
+type record LapdMphActivate {
+};
+type record LapdMphDeactivate {
+};
+type record LapdMphInformation {
+ // connected/disconnected
+};
+
+type union LAPD_Primitive {
+ LAPD_DL_Prim dl,
+ LAPD_MDL_Prim mdl,
+ LAPD_PH_Prim ph,
+ LAPD_MPH_Prim mph
+};
+
+external function f_enc_LAPD_Primitive(in LAPD_Primitive inp) return octetstring
+ with { extension "prototype(convert) encode(JSON)" }
+external function f_dec_LAPD_Primitive(in octetstring inp) return LAPD_Primitive
+ with { extension "prototype(convert) decode(JSON)" }
+
+
+} with { encode "JSON" }
diff --git a/lapd/LAPD_Tests.ttcn b/lapd/LAPD_Tests.ttcn
new file mode 100644
index 00000000..74e95c5f
--- /dev/null
+++ b/lapd/LAPD_Tests.ttcn
@@ -0,0 +1,17 @@
+module LAPD_Tests {
+
+import from LAPD_Types all;
+
+type component test_CT {
+};
+
+
+testcase TC_selftest() runs on test_CT {
+ var LapdAddressField addr;
+
+ addr := { sapi := 62, c_r := true, ea0 := false, tei := 55, ea1 := true };
+ log(enc_LapdAddressField(addr));
+}
+
+
+}
diff --git a/lapd/RLAPD_CodecPort.ttcn b/lapd/RLAPD_CodecPort.ttcn
new file mode 100644
index 00000000..e9f4c632
--- /dev/null
+++ b/lapd/RLAPD_CodecPort.ttcn
@@ -0,0 +1,64 @@
+module RLAPD_CodecPort {
+
+/* Simple RLAPD Codec Port, translating between raw TCP octetstring payload
+ * towards the IPL4asp port provider, and RLAPD primitives
+ * which carry the decoded RLAPD data types as payload.
+ *
+ * (C) 2020 by Harald Welte <laforge@gnumonks.org>
+ * All rights reserved.
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ */
+
+
+import from IPL4asp_PortType all;
+import from IPL4asp_Types all;
+import from LAPD_Primitives all;
+
+type record RLAPD_RecvFrom {
+ ConnectionId connId,
+ LAPD_Primitive msg
+}
+
+type record RLAPD_Send {
+ ConnectionId connId,
+ LAPD_Primitive msg
+}
+
+template (value) RLAPD_Send ts_RLAPD_Send(ConnectionId conn_id, template (value) LAPD_Primitive msg) := {
+ connId := conn_id,
+ msg := msg
+}
+
+template RLAPD_RecvFrom tr_RLAPD_Recv(template ConnectionId conn_id, template LAPD_Primitive msg) := {
+ connId := conn_id,
+ msg := msg
+}
+
+private function IPL4_to_RLAPD_RecvFrom(in ASP_RecvFrom pin, out RLAPD_RecvFrom pout) {
+ pout.connId := pin.connId;
+ pout.msg := f_dec_LAPD_Primitive(pin.msg);
+} with { extension "prototype(fast)" }
+
+private function RLAPD_to_IPL4_Send(in RLAPD_Send pin, out ASP_Send pout) {
+ pout.connId := pin.connId;
+ pout.proto := { sctp := {} };
+ pout.msg := f_enc_LAPD_Primitive(pin.msg);
+} with { extension "prototype(fast)" }
+
+type port RLAPD_CODEC_PT message {
+ out RLAPD_Send;
+ in RLAPD_RecvFrom,
+ ASP_ConnId_ReadyToRelease,
+ ASP_Event;
+} with { extension "user IPL4asp_PT
+ out(RLAPD_Send -> ASP_Send: function(RLAPD_to_IPL4_Send))
+ in(ASP_RecvFrom -> RLAPD_RecvFrom: function(IPL4_to_RLAPD_RecvFrom);
+ ASP_ConnId_ReadyToRelease -> ASP_ConnId_ReadyToRelease: simple;
+ ASP_Event -> ASP_Event: simple)"
+}
+
+
+
+}
diff --git a/lapd/RLAPD_CodecPort_CtrlFunct.ttcn b/lapd/RLAPD_CodecPort_CtrlFunct.ttcn
new file mode 100644
index 00000000..a0280fb2
--- /dev/null
+++ b/lapd/RLAPD_CodecPort_CtrlFunct.ttcn
@@ -0,0 +1,52 @@
+module RLAPD_CodecPort_CtrlFunct {
+
+ import from RLAPD_CodecPort all;
+ import from IPL4asp_Types all;
+
+ external function f_IPL4_listen(
+ inout RLAPD_CODEC_PT portRef,
+ in HostName locName,
+ in PortNumber locPort,
+ in ProtoTuple proto,
+ in OptionList options := {}
+ ) return Result;
+
+ external function f_IPL4_connect(
+ inout RLAPD_CODEC_PT portRef,
+ in HostName remName,
+ in PortNumber remPort,
+ in HostName locName,
+ in PortNumber locPort,
+ in ConnectionId connId,
+ in ProtoTuple proto,
+ in OptionList options := {}
+ ) return Result;
+
+ external function f_IPL4_close(
+ inout RLAPD_CODEC_PT portRef,
+ in ConnectionId id,
+ in ProtoTuple proto := { unspecified := {} }
+ ) return Result;
+
+ external function f_IPL4_setUserData(
+ inout RLAPD_CODEC_PT portRef,
+ in ConnectionId id,
+ in UserData userData
+ ) return Result;
+
+ external function f_IPL4_getUserData(
+ inout RLAPD_CODEC_PT portRef,
+ in ConnectionId id,
+ out UserData userData
+ ) return Result;
+
+ external function f_IPL4_setGetMsgLen(
+ inout RLAPD_CODEC_PT portRef,
+ in ConnectionId id,
+ inout f_IPL4_getMsgLen f,
+ in ro_integer msgLenArgs
+ );
+
+
+}
+
diff --git a/lapd/RLAPD_CodecPort_CtrlFunctDef.cc b/lapd/RLAPD_CodecPort_CtrlFunctDef.cc
new file mode 100644
index 00000000..8c1efe9a
--- /dev/null
+++ b/lapd/RLAPD_CodecPort_CtrlFunctDef.cc
@@ -0,0 +1,66 @@
+#include "IPL4asp_PortType.hh"
+#include "RLAPD_CodecPort.hh"
+#include "IPL4asp_PT.hh"
+
+namespace RLAPD__CodecPort__CtrlFunct {
+
+ IPL4asp__Types::Result f__IPL4__listen(
+ RLAPD__CodecPort::RLAPD__CODEC__PT& portRef,
+ const IPL4asp__Types::HostName& locName,
+ const IPL4asp__Types::PortNumber& locPort,
+ const IPL4asp__Types::ProtoTuple& proto,
+ const IPL4asp__Types::OptionList& options)
+ {
+ return f__IPL4__PROVIDER__listen(portRef, locName, locPort, proto, options);
+ }
+
+ IPL4asp__Types::Result f__IPL4__connect(
+ RLAPD__CodecPort::RLAPD__CODEC__PT& portRef,
+ const IPL4asp__Types::HostName& remName,
+ const IPL4asp__Types::PortNumber& remPort,
+ const IPL4asp__Types::HostName& locName,
+ const IPL4asp__Types::PortNumber& locPort,
+ const IPL4asp__Types::ConnectionId& connId,
+ const IPL4asp__Types::ProtoTuple& proto,
+ const IPL4asp__Types::OptionList& options)
+ {
+ return f__IPL4__PROVIDER__connect(portRef, remName, remPort,
+ locName, locPort, connId, proto, options);
+ }
+
+ IPL4asp__Types::Result f__IPL4__close(
+ RLAPD__CodecPort::RLAPD__CODEC__PT& portRef,
+ const IPL4asp__Types::ConnectionId& connId,
+ const IPL4asp__Types::ProtoTuple& proto)
+ {
+ return f__IPL4__PROVIDER__close(portRef, connId, proto);
+ }
+
+ IPL4asp__Types::Result f__IPL4__setUserData(
+ RLAPD__CodecPort::RLAPD__CODEC__PT& portRef,
+ const IPL4asp__Types::ConnectionId& connId,
+ const IPL4asp__Types::UserData& userData)
+ {
+ return f__IPL4__PROVIDER__setUserData(portRef, connId, userData);
+ }
+
+ IPL4asp__Types::Result f__IPL4__getUserData(
+ RLAPD__CodecPort::RLAPD__CODEC__PT& portRef,
+ const IPL4asp__Types::ConnectionId& connId,
+ IPL4asp__Types::UserData& userData)
+ {
+ return f__IPL4__PROVIDER__getUserData(portRef, connId, userData);
+ }
+
+ void f__IPL4__setGetMsgLen(
+ RLAPD__CodecPort::RLAPD__CODEC__PT& portRef,
+ const IPL4asp__Types::ConnectionId& connId,
+ Socket__API__Definitions::f__getMsgLen& f,
+ const Socket__API__Definitions::ro__integer& msgLenArgs)
+ {
+ return f__IPL4__PROVIDER__setGetMsgLen(portRef, connId, f, msgLenArgs);
+ }
+
+
+}
+
diff --git a/lapd/gen_links.sh b/lapd/gen_links.sh
new file mode 100755
index 00000000..ecdf2e45
--- /dev/null
+++ b/lapd/gen_links.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+BASEDIR=../deps
+
+. ../gen_links.sh.inc
+
+DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
+FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCInterface.cc TCCInterface_ip.h"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.Common_Components.Socket-API/src
+FILES="Socket_API_Definitions.ttcn"
+gen_links $DIR $FILES
+
+DIR=$BASEDIR/titan.TestPorts.IPL4asp/src
+FILES="IPL4asp_Functions.ttcn IPL4asp_PT.cc IPL4asp_PT.hh IPL4asp_PortType.ttcn IPL4asp_Types.ttcn IPL4asp_discovery.cc IPL4asp_protocol_L234.hh"
+gen_links $DIR $FILES
+
+DIR=../library
+FILES="Misc_Helpers.ttcn General_Types.ttcn Osmocom_Types.ttcn LAPD_Types.ttcn "
+gen_links $DIR $FILES
+
+ignore_pp_results
diff --git a/lapd/regen_makefile.sh b/lapd/regen_makefile.sh
new file mode 100755
index 00000000..6f8af367
--- /dev/null
+++ b/lapd/regen_makefile.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+FILES="*.ttcn IPL4asp_PT.cc IPL4asp_discovery.cc TCCConversion.cc TCCInterface.cc "
+FILES+="RLAPD_CodecPort_CtrlFunctDef.cc "
+
+../regen-makefile.sh LAPD_Tests.ttcn $FILES
diff --git a/library/LAPD_Types.ttcn b/library/LAPD_Types.ttcn
new file mode 100644
index 00000000..6e6cc7b9
--- /dev/null
+++ b/library/LAPD_Types.ttcn
@@ -0,0 +1,413 @@
+/* LAPDm definitions according to ITU-T Q.921
+ * (C) 2017-2020 by Harald Welte <laforge@gnumonks.org>
+ * All rights reserved.
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+module LAPD_Types {
+
+import from General_Types all;
+import from Osmocom_Types all;
+
+type uint6_t LapdSapi;
+type uint7_t LapdTei;
+type BIT2 LapdSBits;
+type BIT3 LapdUBits;
+type BIT2 LapdU2Bits;
+
+/* Section 3.3.2 / Table 1*/
+const boolean cr_UO_CMD := false;
+const boolean cr_UO_RSP := true;
+const boolean cr_UT_CMD := true;
+const boolean cr_UT_RSP := false;
+
+/* Figure 5 */
+type record LapdAddressField {
+ LapdSapi sapi,
+ boolean c_r,
+ boolean ea0 (false),
+ LapdTei tei,
+ boolean ea1 (true)
+} with { variant "FIELDORDER(msb)" };
+
+template (present) LapdAddressField
+tr_LapdAddr(template (present) LapdTei tei := ?,
+ template (present) LapdSapi sapi := ?,
+ template (present) boolean c_r) := {
+ sapi := sapi,
+ c_r := c_r,
+ ea0 := false,
+ tei := tei,
+ ea1 := true
+};
+
+template (value) LapdAddressField
+ts_LapdAddr(template (value) LapdTei tei,
+ template (value) LapdSapi sapi, boolean c_r) := {
+ sapi := sapi,
+ c_r := c_r,
+ ea0 := false,
+ tei := tei,
+ ea1 := true
+};
+
+/* Table 4 */
+type record LapdCtrlI {
+ uint7_t n_s,
+ BIT1 spare ('0'B),
+ uint7_t n_r,
+ boolean p
+} with { variant "FIELDORDER(msb)" };
+
+type record LapdCtrlS {
+ BIT4 reserved ('0000'B),
+ LapdSBits s,
+ BIT2 spare ('01'B),
+ uint8_t n_r,
+ boolean p_f
+} with { variant "FIELDORDER(msb)" };
+
+type record LapdCtrlU {
+ LapdUBits u,
+ boolean p_f,
+ LapdU2Bits u2,
+ BIT2 spare ('11'B)
+} with { variant "FIELDORDER(msb)" };
+
+type union LapdCtrl {
+ LapdCtrlS s,
+ LapdCtrlU u,
+ LapdCtrlI i,
+ uint8_t other
+} with { variant "TAG(u, spare = '11'B;
+ s, spare = '01'B;
+ i, spare = '0'B;
+ other, OTHERWISE)" };
+ /* )" }; */
+
+
+template (present) LapdCtrl tr_LapdCtrlU := {
+ u := { u := ?, p_f := ?, u2 := ?, spare := '11'B }
+};
+
+template (present) LapdCtrl tr_LapdCtrlS := {
+ s := { reserved := '0000'B, s := ?, spare := '01'B, n_r := ?, p_f := ? }
+};
+
+template (present) LapdCtrl
+tr_LapdCtrlI(template (present) uint7_t nr, template (present) uint7_t ns,
+ template (present) boolean p) := {
+ i := { n_s := ns, spare := '0'B, n_r := nr, p := p }
+};
+template (value) LapdCtrl
+ts_LapdCtrlI(uint7_t nr, uint7_t ns, boolean p) := {
+ i := { n_s := ns, spare := '0'B, n_r := nr, p := p }
+};
+
+template (present) LapdCtrl
+tr_LapdCtrlRR(template (present) uint7_t nr, template (present) boolean pf)
+modifies tr_LapdCtrlS := {
+ s := { s := '00'B, n_r := nr, p_f := pf }
+};
+template (value) LapdCtrl ts_LapdCtrlRR(uint7_t nr, boolean pf) := {
+ s := { reserved := '0000'B, s := '00'B, spare := '01'B, n_r := nr, p_f := pf }
+};
+
+template (present) LapdCtrl
+tr_LapdCtrlRNR(template (present) uint7_t nr, template (present) boolean pf)
+modifies tr_LapdCtrlS := {
+ s := { s := '01'B, n_r := nr, p_f := pf }
+};
+
+template (present) LapdCtrl
+tr_LapdCtrlREJ(template (present) uint7_t nr, template (present) boolean pf)
+modifies tr_LapdCtrlS := {
+ s := { s := '10'B, n_r := nr, p_f := pf }
+};
+template (value) LapdCtrl
+ts_LapdCtrlREJ(uint7_t nr, boolean pf) := {
+ s := { reserved := '0000'B, s := '10'B, spare := '01'B, n_r := nr, p_f := pf }
+};
+
+template (present) LapdCtrl
+tr_LapdCtrlSABM(template (present) boolean p) := {
+ u := { u := '001'B, p_f := p, u2 := '11'B, spare := '11'B }
+};
+template (value) LapdCtrl
+ts_LapdCtrlSABM(boolean p) := {
+ u := { u := '001'B, p_f := p, u2 := '11'B, spare := '11'B }
+};
+
+template (present) LapdCtrl
+tr_LapdCtrlDM(template (present) boolean f) := {
+ u := { u := '000'B, p_f := f, u2 := '11'B, spare := '11'B }
+};
+template (value) LapdCtrl
+ts_LapdCtrlDM(boolean f) := {
+ u := { u := '000'B, p_f := f, u2 := '11'B, spare := '11'B }
+};
+
+template (present) LapdCtrl
+tr_LapdCtrlUI(template (present) boolean p := false) := {
+ u := { u := '000'B, p_f := p, u2 := '00'B, spare := '11'B }
+};
+template (value) LapdCtrl
+ts_LapdCtrlUI(boolean p := false) := {
+ u := { u := '000'B, p_f := p, u2 := '00'B, spare := '11'B }
+};
+
+template (present) LapdCtrl
+tr_LapdCtrlDISC(template (present) boolean p) := {
+ u := { u := '010'B, p_f := p, u2 := '00'B, spare := '11'B }
+};
+template (value) LapdCtrl
+ts_LapdCtrlDISC(boolean p) := {
+ u := { u := '010'B, p_f := p, u2 := '00'B, spare := '11'B }
+};
+
+template (present) LapdCtrl
+tr_LapdCtrlUA(template (present) boolean f) modifies tr_LapdCtrlU := {
+ u := { u := '011'B, p_f := f, u2 := '00'B, spare := '11'B }
+};
+template (value) LapdCtrl
+ts_LapdCtrlUA(boolean f) := {
+ u := { u := '011'B, p_f := f, u2 := '00'B, spare := '11'B }
+};
+
+template (present) LapdCtrl
+tr_LapdCtrlFRMR(template (present) boolean f) modifies tr_LapdCtrlU := {
+ u := { u := '100'B, p_f := f, u2 := '01'B, spare := '11'B }
+};
+template (value) LapdCtrl
+ts_LapdCtrlFRMR(boolean f) := {
+ u := { u := '100'B, p_f := f, u2 := '01'B, spare := '11'B }
+};
+
+template (present) LapdCtrl
+tr_LapdCtrlXID(template (present) boolean p_f) modifies tr_LapdCtrlU := {
+ u := { u := '101'B, p_f := p_f, u2 := '11'B, spare := '11'B }
+};
+template (value) LapdCtrl
+ts_LapdCtrlXID(boolean p_f) := {
+ u := { u := '101'B, p_f := p_f, u2 := '11'B, spare := '11'B }
+};
+
+
+external function dec_LapdAddressField(in octetstring stream) return LapdAddressField
+ with { extension "prototype(convert) decode(RAW)" };
+external function enc_LapdAddressField(in LapdAddressField f) return octetstring
+ with { extension "prototype(convert) encode(RAW)" };
+
+external function dec_LapdCtrl(in octetstring stream) return LapdCtrl
+ with { extension "prototype(convert) decode(RAW)" };
+
+external function dec_LapdCtrlU(in octetstring stream) return LapdCtrlU
+ with { extension "prototype(convert) decode(RAW)" };
+
+
+type record LapdFrame {
+ LapdAddressField addr,
+ LapdCtrl ctrl,
+ octetstring payload // zero-length in Frame A
+} with { variant "FIELDORDER(msb)" };
+
+external function enc_LapdFrame(in LapdFrame si) return octetstring
+ with { extension "prototype(convert) encode(RAW)" };
+external function dec_LapdFrame(in octetstring stream) return LapdFrame
+ with { extension "prototype(convert) decode(RAW)" };
+
+template (value) LapdFrame
+ts_LAPD_SABM(LapdTei tei, LapdSapi sapi, boolean c_r, boolean p, octetstring l3) := {
+ addr := ts_LapdAddr(tei, sapi, c_r),
+ ctrl := ts_LapdCtrlSABM(p),
+ payload := l3
+}
+template (present) LapdFrame
+tr_LAPD_SABM(template (present) LapdTei tei, template (present) LapdSapi sapi,
+ template (present) boolean c_r, template (present) boolean p,
+ template (present) octetstring l3) := {
+ addr := tr_LapdAddr(tei, sapi, c_r),
+ ctrl := tr_LapdCtrlSABM(p),
+ payload := l3
+}
+
+template (value) LapdFrame
+ts_LAPD_UA(LapdTei tei, LapdSapi sapi, boolean c_r, boolean f, octetstring l3) := {
+ addr := ts_LapdAddr(tei, sapi, c_r),
+ ctrl := ts_LapdCtrlUA(f),
+ payload := l3
+}
+template (present) LapdFrame
+tr_LAPD_UA(template (present) LapdTei tei, template (present) LapdSapi sapi,
+ template (present) boolean c_r, template (present) boolean f,
+ template (present) octetstring l3) := {
+ addr := tr_LapdAddr(tei, sapi, c_r),
+ ctrl := tr_LapdCtrlUA(f),
+ payload := l3
+}
+
+template (value) LapdFrame
+ts_LAPD_DM(LapdTei tei, LapdSapi sapi, boolean c_r, boolean f) := {
+ addr := ts_LapdAddr(tei, sapi, c_r),
+ ctrl := ts_LapdCtrlDM(f),
+ payload := ''O
+}
+template (present) LapdFrame
+tr_LAPD_DM(template (present) LapdTei tei, template (present) LapdSapi sapi,
+ template (present) boolean c_r, template (present) boolean f) := {
+ addr := tr_LapdAddr(tei, sapi, c_r),
+ ctrl := tr_LapdCtrlDM(f),
+ payload := ''O
+}
+
+template (value) LapdFrame
+ts_LAPD_DISC(LapdTei tei, LapdSapi sapi, boolean c_r, boolean p) := {
+ addr := ts_LapdAddr(tei, sapi, c_r),
+ ctrl := ts_LapdCtrlDISC(p),
+ payload := ''O
+}
+template (present) LapdFrame
+tr_LAPD_DISC(template (present) LapdTei tei, template (present) LapdSapi sapi,
+ template (present) boolean c_r, template (present) boolean p) := {
+ addr := tr_LapdAddr(tei, sapi, c_r),
+ ctrl := tr_LapdCtrlDISC(p),
+ payload := ''O
+}
+
+template (value) LapdFrame
+ts_LAPD_UI(LapdTei tei, LapdSapi sapi, boolean c_r, octetstring l3) := {
+ addr := ts_LapdAddr(tei, sapi, c_r),
+ ctrl := ts_LapdCtrlUI,
+ payload := l3
+}
+template (present) LapdFrame
+tr_LAPD_UI(template (present) LapdTei tei, template (present) LapdSapi sapi,
+ template (present) boolean c_r, template (present) octetstring l3) := {
+ addr := tr_LapdAddr(tei, sapi, c_r),
+ ctrl := tr_LapdCtrlUI,
+ payload := l3
+}
+
+template (value) LapdFrame
+ts_LAPD_I(LapdTei tei, LapdSapi sapi, boolean c_r, boolean p, uint7_t nr,
+ uint7_t ns, octetstring l3, boolean m := false) := {
+ addr := ts_LapdAddr(tei, sapi, c_r),
+ ctrl := ts_LapdCtrlI(nr, ns, p),
+ payload := l3
+}
+template (present) LapdFrame
+tr_LAPD_I(template (present) LapdTei tei, template (present) LapdSapi sapi,
+ template (present) boolean c_r, template (present) boolean p,
+ template (present) uint7_t nr, template (present) uint7_t ns,
+ template (present) octetstring l3, template (present) boolean m := false) := {
+ addr := tr_LapdAddr(tei, sapi, c_r),
+ ctrl := tr_LapdCtrlI(nr, ns, p),
+ payload := l3
+}
+
+template (value) LapdFrame
+ts_LAPD_RR(LapdTei tei, LapdSapi sapi, boolean c_r, boolean p, uint7_t nr) := {
+ addr := ts_LapdAddr(tei, sapi, c_r),
+ ctrl := ts_LapdCtrlRR(nr, p),
+ payload := ''O
+}
+template (present) LapdFrame
+tr_LAPD_RR(template (present) LapdTei tei, template (present) LapdSapi sapi,
+ template (present) boolean c_r, template (present) boolean p,
+ template (present) uint7_t nr) := {
+ addr := tr_LapdAddr(tei, sapi, c_r),
+ ctrl := tr_LapdCtrlRR(nr, p),
+ payload := ''O
+}
+
+template (value) LapdFrame ts_LAPD_REJ(LapdTei tei, LapdSapi sapi, boolean c_r,
+ boolean p, uint7_t nr) := {
+ addr := ts_LapdAddr(tei, sapi, c_r),
+ ctrl := ts_LapdCtrlREJ(nr, p),
+ payload := ''O
+}
+template (present) LapdFrame
+tr_LAPD_REJ(template (present) LapdTei tei, template (present) LapdSapi sapi,
+ template (present) boolean c_r, template (present) boolean p,
+ template (present) uint7_t nr) := {
+ addr := tr_LapdAddr(tei, sapi, c_r),
+ ctrl := tr_LapdCtrlREJ(nr, p),
+ payload := ''O
+}
+
+
+/* Table 8/Q.921 */
+type enumerated TeiMgmtMsgType {
+ IDENTITY_REQUEST ('00000001'B),
+ IDENTITY_ASSIGNED ('00000010'B),
+ IDENTITY_DENIED ('00000011'B),
+ IDENTITY_CHECK_REQ ('00000100'B),
+ IDENTITY_CHECK_RESP ('00000101'B),
+ IDENTITY_REMOVE ('00000110'B),
+ IDENTITY_VERIFY ('00000111'B)
+} with { variant "FIELDLENGTH(8)" };
+type record TeiMgmtMsg {
+ BIT8 me_id ('00001111'B), /* management entity identifier */
+ uint16_t ri, /* reference number */
+ TeiMgmtMsgType msg_type,
+ uint7_t ai,
+ BIT1 e
+};
+
+template (value) TeiMgmtMsg ts_TEI(TeiMgmtMsgType msgt, uint16_t ri, uint7_t ai) := {
+ me_id := '00001111'B,
+ ri := ri,
+ msg_type := msgt,
+ ai := ai,
+ e := '1'B
+}
+
+external function enc_TeiMgmtMsg(in TeiMgmtMsg si) return octetstring
+ with { extension "prototype(convert) encode(RAW)" };
+external function dec_TeiMgmtMsg(in octetstring stream) return TeiMgmtMsg
+ with { extension "prototype(convert) decode(RAW)" };
+
+template (value) TeiMgmtMsg
+ts_TEI_IdRequest(uint16_t ri, uint7_t ai) := ts_TEI(IDENTITY_REQUEST, ri, ai);
+
+template (value) TeiMgmtMsg
+ts_TEI_IdAssigned(uint16_t ri, uint7_t ai) := ts_TEI(IDENTITY_ASSIGNED, ri, ai);
+
+template (value) TeiMgmtMsg
+ts_TEI_IdDenied(uint16_t ri, uint7_t ai) := ts_TEI(IDENTITY_DENIED, ri, ai);
+
+template (value) TeiMgmtMsg
+ts_TEI_IdCheckReq(uint16_t ri, uint7_t ai) := ts_TEI(IDENTITY_CHECK_REQ, ri, ai);
+
+template (value) TeiMgmtMsg
+ts_TEI_IdCheckResp(uint16_t ri, uint7_t ai) := ts_TEI(IDENTITY_CHECK_RESP, ri, ai);
+
+template (value) TeiMgmtMsg
+ts_TEI_IdRemove(uint16_t ri, uint7_t ai) := ts_TEI(IDENTITY_REMOVE, ri, ai);
+
+template (value) TeiMgmtMsg
+ts_TEI_IdVerify(uint16_t ri, uint7_t ai) := ts_TEI(IDENTITY_VERIFY, ri, ai);
+
+
+/* Q.921bis Name:ID_Rmv */
+template (present) LapdFrame
+tr_ID_Rmv(template (present) LapdTei tei) := {
+ addr := ts_LapdAddr(tei := 127, sapi := 63, c_r := true),
+ ctrl := ts_LapdCtrlUI(p := false)
+}
+
+/* Q.921bis Name:ID_Ver */
+template (present) LapdFrame
+tr_ID_Ver(template (present) LapdTei tei) := {
+ addr := ts_LapdAddr(tei := 127, sapi := 63, c_r := true),
+ ctrl := ts_LapdCtrlUI(p := false)
+}
+
+
+
+
+} with { encode "RAW"; /*variant "FIELDORDER(msb)" */}