src added
diff --git a/src/LLC_EncDec.cc b/src/LLC_EncDec.cc
new file mode 100644
index 0000000..b96b961
--- /dev/null
+++ b/src/LLC_EncDec.cc
@@ -0,0 +1,317 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2000-2017 Ericsson Telecom AB
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// which accompanies this distribution, and is available at
+// http://www.eclipse.org/legal/epl-v10.html
+///////////////////////////////////////////////////////////////////////////////
+//
+// File: LLC_EncDec.cc
+// Rev: R2A
+// Prodnr: CNL 113 577
+// Updated: 2008-01-22
+// Contact: http://ttcn.ericsson.se
+// Reference: 3GPP TS 44.064 7.1.0
+
+#include "LLC_Types.hh"
+#include <string.h>
+
+// GIVEN IN CODE RECEIVED FROM ERV
+#define CRC_POLY_LLC2 0xad85dd
+
+// GIVEN IN SPECIFICATION
+//#define CRC_POLY_LLC2 0xbba1b5
+
+#define TABLE_LENGTH 256
+
+// For UI frames if PM bit is 0 (unprotected) then CRC will be calculated over Header + N202 octets
+#define N202 4
+
+unsigned int mCRCTable[TABLE_LENGTH];
+
+
+static void BuildCrc24Table()
+{
+ unsigned int i,j;
+ unsigned int reg;
+
+ //TRACE_FUNC( "BuildCrc24Table" );
+
+ for( i = 0; i < TABLE_LENGTH; i++ )
+ {
+ reg = i;
+ for( j = 8; j > 0; j-- )
+ {
+ if( reg & 1 )
+ {
+
+ reg = (reg>>1) ^ (unsigned int) CRC_POLY_LLC2;
+ }
+ else
+ {
+ reg >>= 1;
+ }
+ }
+ reg &= 0x00ffffffL;
+
+ mCRCTable[i] = (unsigned int)reg;
+ //TTCN_Logger::begin_event(TTCN_DEBUG);
+
+ //TTCN_Logger::log_event("mCRCTable[%d]= %d",i,mCRCTable[i]);
+
+ // TTCN_Logger::end_event();
+
+ }
+}
+
+//---------------------------------------------------------------------------------------
+
+unsigned int Calculate_CRC(TTCN_Buffer& pdu)
+{
+
+const unsigned char* loc_pdu = pdu.get_data();
+
+ //TTCN_Logger::begin_event(TTCN_DEBUG);
+
+ //for (size_t i =0; i< pdu.get_len();i++)
+ // {
+ // TTCN_Logger::log_event("%02x ",loc_pdu[i]);
+ // }
+
+//TTCN_Logger::log_event("\n");
+
+//TTCN_Logger::end_event();
+
+BuildCrc24Table();
+
+//TTCN_Logger::begin_event(TTCN_DEBUG);
+//TTCN_Logger::log_event("mCRCTable[%d]= %d\n",255,mCRCTable[255]);
+//TTCN_Logger::log_event("mCRCTable[%d]= 0x%08x (%u)",255,mCRCTable[255]);
+//TTCN_Logger::log_event("\n");
+//TTCN_Logger::end_event();
+
+unsigned int reg = 0xFFFFFF;
+
+unsigned int length = pdu.get_len();
+
+
+
+if ( ((loc_pdu[1] >>5) & 0x07) == 0x06 ) //UI frame
+{
+ if ((loc_pdu[2] & 0x01) == 0x00) // PM bit is 0 (unprotected)
+ {
+ if(length > 3 + N202) // pdu length is longer than header + N202
+ {
+ length = 3 + N202; // length = header length + N202
+
+ }
+ }
+}
+
+
+
+while ( length--)
+ {
+ reg =
+ ((reg>>8) & 0x00ffff)^mCRCTable[(reg^*((unsigned char*)loc_pdu++)) & 0xffL];
+ }
+ //TTCN_Logger::log(TTCN_DEBUG, "reg:%08x\n",reg);
+ // 1's complement of FCS
+ reg ^= 0xffffffL;
+
+ reg = ((reg >> 16) & 0x000000ff)+ ((reg) & 0x0000ff00) + ((reg <<16 )& 0x00ff0000);
+ //unsigned int tempint = *(unsigned int*)loc_crcBuffer;
+ //reg = (unsigned int*)loc_crcBuffer ;
+ //TTCN_Logger::log(TTCN_DEBUG, "reg:%08x\n",reg);
+
+return reg & 0x00ffffffL;
+}
+//---------------------------------------------------------------------------------------
+
+namespace LLC__Types {
+
+OCTETSTRING enc__PDU__LLC(const PDU__LLC& pdu)
+{
+ TTCN_Buffer bb;
+ PDU__LLC pdu2(pdu);
+
+ if (pdu2.get_selection() == PDU__LLC::ALT_pDU__LLC__U)
+ {
+
+ if (pdu2.pDU__LLC__U().information__field__U().get_selection() == Information__field__U::ALT_uA)
+ {int record_of_size = pdu2.pDU__LLC__U().information__field__U().uA().size_of();
+
+ for (int i = 0; i < (record_of_size) ; i++)
+ {
+ // AUTOMATICALLY CALCULATE WHICH LENGTH FORMAT SHOULD BE USED AND CHANGE SHORT LENGTH FORM
+ // TO LONG LENGTH FORM IF NECESSARY WHEN L3 PDU IS INCLUDED
+ if ( pdu2.pDU__LLC__U().information__field__U().uA()[i].typefield() == int2bit(11,5) )
+ {
+ if( pdu2.pDU__LLC__U().information__field__U().uA()[i].xID__Data().l3param().lengthof() > 3)
+ {
+ pdu2.pDU__LLC__U().information__field__U().uA()[i].xID__length().long__len() =
+ pdu2.pDU__LLC__U().information__field__U().uA()[i].xID__Data().l3param().lengthof();
+ }
+ }
+ }
+ }
+
+ if (pdu2.pDU__LLC__U().information__field__U().get_selection() == Information__field__U::ALT_sABM)
+ {int record_of_size = pdu2.pDU__LLC__U().information__field__U().sABM().size_of();
+
+ for (int i = 0; i < (record_of_size) ; i++)
+ {
+ // AUTOMATICALLY CALCULATE WHICH LENGTH FORMAT SHOULD BE USED AND CHANGE SHORT LENGTH FORM
+ // TO LONG LENGTH FORM IF NECESSARY WHEN L3 PDU IS INCLUDED
+ if ( pdu2.pDU__LLC__U().information__field__U().sABM()[i].typefield() == int2bit(11,5) )
+ {
+ if( pdu2.pDU__LLC__U().information__field__U().sABM()[i].xID__Data().l3param().lengthof() > 3)
+ {
+ pdu2.pDU__LLC__U().information__field__U().sABM()[i].xID__length().long__len() =
+ pdu2.pDU__LLC__U().information__field__U().sABM()[i].xID__Data().l3param().lengthof();
+ }
+ }
+ }
+ }
+
+ if (pdu2.pDU__LLC__U().information__field__U().get_selection() == Information__field__U::ALT_xID)
+ {int record_of_size = pdu2.pDU__LLC__U().information__field__U().xID().size_of();
+
+ for (int i = 0; i < (record_of_size) ; i++)
+ {
+ // AUTOMATICALLY CALCULATE WHICH LENGTH FORMAT SHOULD BE USED AND CHANGE SHORT LENGTH FORM
+ // TO LONG LENGTH FORM IF NECESSARY WHEN L3 PDU IS INCLUDED
+ if ( pdu2.pDU__LLC__U().information__field__U().xID()[i].typefield() == int2bit(11,5) )
+ {
+ if( pdu2.pDU__LLC__U().information__field__U().xID()[i].xID__Data().l3param().lengthof() > 3)
+ {
+ pdu2.pDU__LLC__U().information__field__U().xID()[i].xID__length().long__len() =
+ pdu2.pDU__LLC__U().information__field__U().xID()[i].xID__Data().l3param().lengthof();
+ }
+ }
+ }
+ }
+ }
+
+
+ if (pdu2.get_selection() == PDU__LLC::ALT_pDU__LLC__U)
+ {
+ if ( pdu2.pDU__LLC__U().fCS().ispresent())
+ {
+ if ( pdu2.pDU__LLC__U().fCS() == int2oct(0,3) ) // IF ENCODER NEEDS TO GENERATE CRC
+ {
+ pdu2.pDU__LLC__U().fCS() = OMIT_VALUE;
+ pdu2.encode(PDU__LLC_descr_ ,bb, TTCN_EncDec::CT_RAW);
+ unsigned int crcBuffer = Calculate_CRC(bb);
+ bb.put_os(int2oct(crcBuffer,3));
+ return OCTETSTRING (bb.get_len(), bb.get_data());
+
+ }
+
+ else { // IF ENCODER SENDS OUT NONZERO CRC GIVEN IN TTCN TEMPLATE
+ pdu2.encode(PDU__LLC_descr_ ,bb, TTCN_EncDec::CT_RAW);
+ return OCTETSTRING (bb.get_len(), bb.get_data());
+ }
+ }
+ else { //FCS OMIT
+ pdu2.encode(PDU__LLC_descr_ ,bb, TTCN_EncDec::CT_RAW);
+ unsigned int crcBuffer = Calculate_CRC(bb);
+ bb.put_os(int2oct(crcBuffer,3));
+ return OCTETSTRING (bb.get_len(), bb.get_data());
+
+ }
+ }
+
+
+
+ else if (pdu2.get_selection() == PDU__LLC::ALT_pDU__LLC__UI)
+ {
+ if ( pdu2.pDU__LLC__UI().fCS().ispresent())
+ {
+ if ( pdu2.pDU__LLC__UI().fCS() == int2oct(0,3) ) // IF ENCODER NEEDS TO GENERATE CRC
+ {
+ pdu2.pDU__LLC__UI().fCS() = OMIT_VALUE;
+ pdu2.encode(PDU__LLC_descr_ ,bb, TTCN_EncDec::CT_RAW);
+ unsigned int crcBuffer = Calculate_CRC(bb);
+ bb.put_os(int2oct(crcBuffer,3));
+ return OCTETSTRING (bb.get_len(), bb.get_data());
+
+ }
+
+ else { // IF ENCODER SENDS OUT NONZERO CRC GIVEN IN TTCN TEMPLATE
+ pdu2.encode(PDU__LLC_descr_ ,bb, TTCN_EncDec::CT_RAW);
+ return OCTETSTRING (bb.get_len(), bb.get_data());
+ }
+ }
+ else { //FCS OMIT
+ pdu2.encode(PDU__LLC_descr_ ,bb, TTCN_EncDec::CT_RAW);
+ unsigned int crcBuffer = Calculate_CRC(bb);
+ bb.put_os(int2oct(crcBuffer,3));
+ return OCTETSTRING (bb.get_len(), bb.get_data());
+ }
+ }
+ else {TTCN_error("Can not encode LLC PDU"); //Neither UI NOR U
+
+ return OCTETSTRING (bb.get_len(), bb.get_data()); // this is dummy to avoid warning during compilation
+ }
+ //pdu2.encode(PDU__LLC_descr_ ,bb, TTCN_EncDec::CT_RAW);
+ //unsigned int crcBuffer = Calculate_CRC(bb);
+
+ //bb.put_os( int2oct(crcBuffer,3));
+
+
+ //return OCTETSTRING (bb.get_len(), bb.get_data());
+
+}
+
+
+OCTETSTRING enc__PDU__LLC(const PDU__LLC_template& pdu)
+{
+ return enc__PDU__LLC(pdu.valueof());
+}
+
+
+PDU__LLC dec__PDU__LLC(const OCTETSTRING& stream)
+{
+ PDU__LLC retv;
+ TTCN_Buffer bb;
+ OCTETSTRING crc = int2oct(0,3);
+
+ size_t datalength = stream.lengthof()-3;
+ const unsigned char * CRC_AS_RECEIVED = (const unsigned char *)stream+datalength;
+ bb.put_s(datalength,(const unsigned char *)stream);
+
+ unsigned int CRC_CALCULATED = Calculate_CRC(bb);
+
+ // COMPARE CRC RECEIVED IN LLC PDU WITH CRC CALCULATED FROM LLC PDU
+ if(
+ (CRC_AS_RECEIVED[ 0 ] != (CRC_CALCULATED & 0xff0000 ) >> 16) ||
+ (CRC_AS_RECEIVED[ 1 ] != (CRC_CALCULATED & 0xff00 ) >> 8) ||
+ (CRC_AS_RECEIVED[ 2 ] != (CRC_CALCULATED & 0xff ) )
+ )
+ {
+ TTCN_warning("CRC ERROR IN LLC PDU"); // CRC IS NOT AS EXPECTED
+ crc=OCTETSTRING(3,CRC_AS_RECEIVED);
+ }
+ // CRC IS
+ // FILL CRC octets with zeroes if CRC is OK
+
+ retv.decode(PDU__LLC_descr_, bb, TTCN_EncDec::CT_RAW);
+
+ if (retv.get_selection() == PDU__LLC::ALT_pDU__LLC__UI){
+ retv.pDU__LLC__UI().fCS() = crc;
+ }
+
+ if (retv.get_selection() == PDU__LLC::ALT_pDU__LLC__U){
+ retv.pDU__LLC__U().fCS() = crc;
+ }
+
+
+ return retv;
+
+
+}
+
+}//namespace
diff --git a/src/LLC_Types.ttcn b/src/LLC_Types.ttcn
new file mode 100644
index 0000000..d07a77f
--- /dev/null
+++ b/src/LLC_Types.ttcn
@@ -0,0 +1,328 @@
+///////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2000-2017 Ericsson Telecom AB
+//
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// which accompanies this distribution, and is available at
+// http://www.eclipse.org/legal/epl-v10.html
+///////////////////////////////////////////////////////////////////////////////
+//
+// File: LLC_Types.ttcn
+// Description: This module contains the Logical Link Control protocol (LLC)
+// 44.064 v7.1.0 with attributes for RAW encoding/decoding.
+// Rev: R2A
+// Prodnr: CNL 113 577
+// Updated: 2008-01-22
+// Contact: http://ttcn.ericsson.se
+// Reference: 3GPP TS 44.064 7.1.0
+
+module LLC_Types
+{
+
+import from General_Types all;
+
+external function enc_PDU_LLC(in PDU_LLC pdu) return octetstring;
+external function dec_PDU_LLC(in octetstring stream) return PDU_LLC;
+
+type record Version
+{
+ integer version_value (0..15),
+ BIT4 spare
+
+} with {
+ variant (version_value) "FIELDLENGTH(4)";
+}
+
+type octetstring IOV_UI length(4)
+
+
+type octetstring IOV_I length(4)
+
+
+type record T200
+{
+ BIT4 spare,
+ integer t200Value
+} with {
+ variant (t200Value) "FIELDLENGTH(12)";
+ variant (t200Value) "BYTEORDER(last)";
+ variant "FIELDORDER(msb)";
+};
+
+
+type record N200
+{
+ integer retransmissions (0..15),
+ BIT4 spare
+} with {
+ variant (retransmissions) "FIELDLENGTH(4)";
+}
+
+
+type record N201_U
+{
+ BIT5 spare,
+ integer n201UValue
+} with {
+ variant (n201UValue) "FIELDLENGTH(11)";
+ variant (n201UValue) "BYTEORDER(last)";
+ variant "FIELDORDER(msb)";
+};
+
+
+type record N201_I
+{
+ BIT5 spare,
+ integer n201IValue
+}
+with {
+ variant (n201IValue) "FIELDLENGTH(11)";
+ variant (n201IValue) "BYTEORDER(last)";
+ variant "FIELDORDER(msb)";
+};
+
+type record MD
+{
+ BIT1 spare,
+ integer mDValue
+} with {
+ variant (mDValue) "FIELDLENGTH(15)";
+ variant (mDValue) "BYTEORDER(last)";
+ variant "FIELDORDER(msb)";
+};
+
+
+type record MU
+{
+ BIT1 spare,
+ integer mUValue
+} with {
+ variant (mUValue) "FIELDLENGTH(15)";
+ variant (mUValue) "BYTEORDER(last)";
+ variant "FIELDORDER(msb)";
+};
+
+type integer KD with {variant "FIELDLENGTH(8)";};
+
+type integer KU with {variant "FIELDLENGTH(8)";};
+
+type octetstring L3param;
+
+type octetstring Reset_LLC length(0);
+
+type union XID_Data
+{
+ Version version,
+ IOV_UI iOV_UI,
+ IOV_I iOV_I,
+ T200 t200,
+ N200 n200,
+ N201_U n201_U,
+ N201_I n201_I,
+ MD mD,
+ MU mU,
+ KD kD,
+ KU kU,
+ L3param l3param,
+ Reset_LLC reset
+}
+
+
+type union XID_length
+{
+ integer short_len,
+ integer long_len
+}with {
+ variant (short_len) "FIELDLENGTH(2)";
+ variant (long_len) "FIELDLENGTH(8)";
+ variant (long_len) "BYTEORDER(last)";
+ variant (short_len) "FIELDORDER(msb)";
+ variant (long_len) "FIELDORDER(msb)";
+
+}
+
+
+type record XID
+{
+ BIT1 xl,
+ BIT5 typefield,
+ XID_length xID_length,
+ //Header_XID header_XID,
+ XID_Data xID_Data
+} with {
+ variant (xID_Data) "CROSSTAG( version, typefield = '00000'B;
+ iOV_UI, typefield = '00001'B;
+ iOV_I, typefield = '00010'B;
+ t200, typefield = '00011'B;
+ n200, typefield = '00100'B;
+ n201_U, typefield = '00101'B;
+ n201_I, typefield = '00110'B;
+ mD, typefield = '00111'B;
+ mU, typefield = '01000'B;
+ kD, typefield = '01001'B;
+ kU, typefield = '01010'B;
+ l3param, typefield = '01011'B;
+ reset, typefield = '01100'B;
+
+ )";
+ variant "FIELDORDER(msb)";
+ variant (xID_length) "CROSSTAG( short_len, xl = '0'B;
+ long_len, xl = '1'B;)";
+ variant (xID_length) "LENGTHTO (xID_Data)"
+
+ variant (xID_length) "PADDING(yes)"
+};
+
+
+type record RejectedFrameControlField_UI
+{
+ Control_field_UI control_field,
+ OCT4 spare
+}
+
+
+type record RejectedFrameControlField_U
+{
+ Control_field_U control_field,
+ OCT5 spare
+}
+
+
+type union RejectedFrameControlField
+{
+ RejectedFrameControlField_UI rejectedFrameControlField_UI,
+ RejectedFrameControlField_U rejectedFrameControlField_U
+} with {
+ variant "TAG(rejectedFrameControlField_UI, control_field.format = '110'B;
+ rejectedFrameControlField_U, control_field.format = '111'B;
+ )";
+};
+
+
+type record of XID UA_Information;
+
+type record of XID SABM_Information;
+
+type record of XID XID_Information;
+
+
+type octetstring DM_Information length(0);
+
+
+type record FRMR_Information
+{
+ RejectedFrameControlField rejectedFrameControlField,
+ BIT4 spare1,
+ BIT9 vS,
+ BIT1 spare2,
+ BIT9 vR,
+ BIT1 cR,
+ BIT4 spare3,
+ BIT1 w4,
+ BIT1 w3,
+ BIT1 w2,
+ BIT1 w1
+} with {
+ variant (vS) "BYTEORDER(last)";
+ variant (vR) "BYTEORDER(last)";
+ variant "FIELDORDER(msb)";
+};
+
+
+type record Address_field
+{
+ BIT4 sAPI,
+ BIT2 spare, // '00'B
+ BIT1 cR,
+ BIT1 pD //'0' for LLC
+}
+
+type record Control_field_U
+{
+ BIT4 mBits,
+ BIT1 pF,
+ BIT3 format // '111'B
+}
+
+
+
+type record Control_field_UI
+
+{
+ BIT3 format, // '110'B
+ BIT2 spare,
+ integer nU, //BIT9
+ BIT1 e,
+ BIT1 pM
+} with {
+
+ variant (nU) "FIELDLENGTH(9)";
+ variant (nU) "BYTEORDER(last)";
+ variant "FIELDORDER(msb)";
+}
+
+
+type union Information_field_U
+{
+ UA_Information uA,
+ SABM_Information sABM,
+ FRMR_Information fRMR,
+ DM_Information dM,
+ XID_Information xID
+};
+
+
+type record PDU_LLC_UI
+{
+ Address_field address_field,
+ Control_field_UI control_field,
+ octetstring information_field_UI,
+ OCT3 fCS optional
+ // fCS ENCODING:
+ //'000000'O in send template -> generate CRC,
+ // omit in send template -> generate CRC,
+ // otherwise send out fCS in send template
+ //
+ // DECODING:
+ // decoder generates '000000'O if CRC OK
+}
+
+
+
+type record PDU_LLC_U
+{
+ Address_field address_field,
+ Control_field_U control_field,
+ Information_field_U information_field_U,
+ OCT3 fCS optional
+ // ENCODING:
+ //'000000'O in send template -> generate CRC,
+ // omit in send template -> generate CRC,
+ // otherwise send out fCS in send template
+ //
+ // DECODING:
+ // decoder generates '000000'O if CRC OK
+} with {
+ variant (information_field_U) "CROSSTAG( uA, control_field.mBits = '0110'B;
+ sABM, control_field.mBits = '0111'B;
+ fRMR, control_field.mBits = '1000'B;
+ dM, control_field.mBits = '0001'B;
+ xID, control_field.mBits = '1011'B;
+ )";
+};
+
+
+type union PDU_LLC
+{
+ PDU_LLC_UI pDU_LLC_UI,
+ PDU_LLC_U pDU_LLC_U
+} with { variant "TAG (
+ pDU_LLC_UI, control_field.format ='110'B;
+ pDU_LLC_U, control_field.format ='111'B;
+ )"
+};
+
+
+
+}with{ encode "RAW"}// end of module