First steps towards an open source implementation of the LE (Local Exchange) side of the ETSI/ITU V5 interface, in order to talk to Access Multiplexers (AN), such as Nokia EKSOS, DeTeWe ALIAN, etc.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
osmo-v5/v5x_protocol.h

252 lines
7.7 KiB

#pragma once
#include <stdint.h>
#include <osmocom/core/utils.h>
#include <osmocom/gsm/tlv.h>
/* Definitions related to the V5.1 and V5.2 interface between AN (access
* network) and LE (local exchange) as per ITU-T G.964 + G.965.
*
* (C) 2021 by Harald Welte <laforge@gnumonks.org>
*/
/***********************************************************************/
/* protocol wire format */
/***********************************************************************/
/* Table 14/G.964 */
#define V51_CTRL_PDISC 0x48
/* Table 1/G.965 + Table 1/G.964 */
#define V51_DLADDR_PSTN 8176
#define V51_DLADDR_CTRL 8177
#define V52_DLADDR_BCC 8178
#define V52_DLADDR_PROTECTION 8179
#define V52_DLADDR_LCP 8180
/* G.965 Section 13.1 */
struct v51_l3_hdr {
uint8_t pdisc;
uint16_t l3_addr; /* with C/R and EA bits! */
uint8_t msg_type;
uint8_t payload[0];
} __attribute__ ((packed));
/* G.964 Section 14.4.2.3 Figure 33 + 34 */
static inline bool v51_l3_addr_is_isdn(uint16_t in)
{
/* extract two bytes */
uint8_t b1 = in >> 8;
uint8_t b2 = in & 0xff;
if ((b1 & 0x03) == 0x00 && (b2 & 0x01))
return true;
return false;
}
static inline uint16_t v51_l3_addr_dec(uint16_t in, bool *is_isdn)
{
/* extract two bytes */
uint8_t b1 = in >> 8;
uint8_t b2 = in & 0xff;
if (v51_l3_addr_is_isdn(in)) {
/* remove EA/C/R bits */
uint8_t upper = b1 >> 2;
uint8_t lower = b2 >> 1;
if (is_isdn)
*is_isdn = true;
/* shift them together */
return lower | (upper << 7);
} else{
uint8_t upper = b1 >> 1;
uint8_t lower = b2;
if (is_isdn)
*is_isdn = false;
return lower | (upper << 8);
}
}
static inline uint16_t v51_l3_addr_enc(uint16_t in, bool is_isdn)
{
uint8_t b1, b2;
if (is_isdn) {
uint8_t upper = in >> 7;
uint8_t lower = in & 0x7f;
b1 = upper << 2;
b2 = (lower << 1) | 0x01;
} else {
uint8_t upper = in >> 8;
uint8_t lower = in & 0xff;
b1 = (upper << 1) | 0x01;
b2 = lower;
}
return (b1 << 8) | b2;
}
/* Table 15 + 52/G.964 */
enum v51_ctrl_msg_type {
/* 000xxxx: PSTN protocol message types */
V51_CTRL_MSGT_ESTABLISH = 0x00,
V51_CTRL_MSGT_ESTABLISH_ACK = 0x01,
V51_CTRL_MSGT_SIGNAL = 0x02,
V51_CTRL_MSGT_SIGNAL_ACK = 0x03,
V51_CTRL_MSGT_DISCONNECT = 0x08,
V51_CTRL_MSGT_DISCONNECT_ACK = 0x09,
V51_CTRL_MSGT_STATUS_ENQUIRY = 0x0c,
V51_CTRL_MSGT_STATUS = 0x0d,
V51_CTRL_MSGT_PROTOCOL_PARAMETER = 0x0e,
/* 0010xxx: Control protocol message types */
V51_CTRL_MSGT_PORT_CTRL = 0x10,
V51_CTRL_MSGT_PORT_CTRL_ACK = 0x11,
V51_CTRL_MSGT_COMMON_CTRL = 0x12,
V51_CTRL_MSGT_COMMON_CTRL_ACK = 0x13,
/* 0011xxx: Protection protocol message types */
V52_CTRL_MSGT_PP_SWITCH_OVER_REQ = 0x18,
V52_CTRL_MSGT_PP_SWITCH_OVER_COM = 0x19,
V52_CTRL_MSGT_PP_OS_SWITCH_OVER_COM = 0x1a,
V52_CTRL_MSGT_PP_SWITCH_OVER_ACK = 0x1b,
V52_CTRL_MSGT_PP_SWITCH_OVER_REJECT = 0x1c,
V52_CTRL_MSGT_PP_PROTOCOL_ERROR = 0x1d,
V52_CTRL_MSGT_PP_RESET_SN_COM = 0x1e,
V52_CTRL_MSGT_PP_RESET_SN_ACK = 0x1f,
/* 010xxxx: BCC protocol message types */
V52_CTRL_MSGT_ALLOCATION = 0x20,
V52_CTRL_MSGT_ALLOCATION_COMPLETE = 0x21,
V52_CTRL_MSGT_ALLOCATION_REJECT = 0x22,
V52_CTRL_MSGT_DE_ALLOCATION = 0x23,
V52_CTRL_MSGT_DE_ALLOCATION_COMPLETE = 0x24,
V52_CTRL_MSGT_DE_ALLOCATION_REJECT = 0x25,
V52_CTRL_MSGT_AUDIT = 0x26,
V52_CTRL_MSGT_AUDIT_COMPLETE = 0x27,
V52_CTRL_MSGT_AN_FAULT = 0x28,
V52_CTRL_MSGT_AN_FAULT_ACK = 0x29,
V52_CTRL_MSGT_PROTOCOL_ERROR = 0x2a,
/* 0110xxx: Link control protocol message types */
V52_CTRL_MSGT_LCP_LINK_CTRL = 0x30,
V52_CTRL_MSGT_LCP_LINK_CTRL_ACK = 0x31,
};
extern const struct value_string v51_ctrl_msg_typ_str[];
/* Table 17 + 53/G.964 */
enum v51_ctrl_iei {
/* single byte, only upper nibble matches IEI */
V51_CTRL_IEI_PULSE_NOTIFICATION = 0xc0,
V51_CTLR_IEI_LINE_NOTIFICATION = 0x80,
V51_CTLR_IEI_STATE = 0x90,
V51_CTLR_IEI_AUTONOMOUS_SIG_SEQ = 0xa0,
V51_CTLR_IEI_SEQUENCE_RESPONSE = 0xb0,
/* single byte: ISDN */
V51_CTRL_IEI_PERFORMANCE_GRADING = 0xe0,
V51_CTRL_IEI_REJECTION_CAUSE = 0xf0,
/* variable length: PSTN */
V51_CTRL_IEI_SEQUENCE_NR = 0x00,
V51_CTRL_IEI_CADENCED_RINGING = 0x01,
V51_CTRL_IEI_PULSED_SIGNAL = 0x02,
V51_CTRL_IEI_STEADY_SIGNAL = 0x03,
V51_CTRL_IEI_DIGIT_SIGNAL = 0x04,
V51_CTRL_IEI_RECOGNITION_TIME = 0x10,
V51_CTRL_IEI_ENABLE_AUTONOMOUS_ACK = 0x11,
V51_CTRL_IEI_DISABLE_AUTONOMOUS_ACK = 0x12,
V51_CTRL_IEI_CAUSE = 0x13,
V51_CTRL_IEI_RESOURCE_UNAVAILABLE = 0x14,
V51_CTRL_IEI_ENABLE_METERING = 0x32,
V51_CTRL_IEI_METERING_REPORT = 0x33,
V51_CTRL_IEI_ATTENUATION = 0x34,
/* variable length: ISDN */
V51_CTRL_IEI_CTRL_F_ELEMENT = 0x20,
V51_CTRL_IEI_CTRL_F_ID = 0x21,
V51_CTRL_IEI_VARIANT = 0x22,
V51_CTRL_IEI_INTERFACE_ID = 0x23,
/* variable length: LCP */
V52_CTRL_IEI_LCP_LINK_CTRL_FUNCTION = 0x30,
/* variable length: BCC */
V52_CTRL_IEI_BCC_USER_PORT_ID = 0x40,
V52_CTRL_IEI_BCC_ISDN_PORT_TS_ID = 0x41,
V52_CTRL_IEI_BCC_V5_TS_ID = 0x42,
V52_CTRL_IEI_BCC_MULTI_TS_MAP = 0x43,
V52_CTRL_IEI_BCC_REJECT_CAUSE = 0x44,
V52_CTRL_IEI_BCC_PROTOCOL_ERROR_CAUSE = 0x45,
V52_CTRL_IEI_BCC_CONNECTION_INCOMPLETE = 0x46,
V52_CTRL_IEI_BCC_INFO_TRANSFER_CAPABILITY = 0x47,
/* variable-length: Protection */
V52_CTRL_IEI_PP_SEQUENCE_NR = 0x50,
V52_CTRL_IEI_PP_PHYSICAL_C_CHAN_ID = 0x51,
V52_CTRL_IEI_PP_REJECTION_CAUSE = 0x52,
V52_CTRL_IEI_PP_PROTOCOL_ERROR_CAUSE = 0x53,
};
extern const struct value_string v51_ctrl_iei_str[];
extern const struct tlv_definition v51_ctrl_tlv_def[];
extern const struct osmo_tlv_prot_def v51_ctrl_msg_tlv;
/* 14.4.2.5.4 Table 56/G.964 - Coding of Control Function Element */
enum v51_ctrl_func_el {
V51_CTRL_FE101_ACTIVATE_ACCESS = 0x01,
V51_CTRL_FE102_ACT_INIT_BY_USER = 0x02,
V51_CTRL_FE103_DS_ACTIVATED = 0x03,
V51_CTRL_FE104_ACCESS_ACTIVATED = 0x04,
V51_CTRL_FE105_DEACTIVATE_ACCESS = 0x05,
V51_CTRL_FE106_ACCESS_DEACTIVATED = 0x06,
V51_CTRL_FE201_UNBLOCK = 0x11,
V51_CTRL_FE203_BLOCK = 0x13,
V51_CTRL_FE205_BLOCK_REQ = 0x15,
V51_CTRL_FE206_PERFORMANCE_GRADING = 0x16,
V51_CTRL_FE207_D_CHANNEL_BLOCK = 0x17,
V51_CTRL_FE208_D_CHANNEL_UNBLOCK = 0x18,
};
extern const struct value_string v51_ctrl_func_el_str[];
/* 14.4.2.5.5 Table 57/G.964 - Coding of Control Function ID */
enum v51_ctrl_func_id {
V51_CTRL_ID_VERIFY_RE_PROVISIONING = 0x00,
V51_CTRL_ID_READY_FOR_RE_PROVISIONING = 0x01,
V51_CTRL_ID_NOT_READY_FOR_RE_PROVISIONING = 0x02,
V51_CTRL_ID_SWITCH_OVER_TO_NEW_VARIANT = 0x03,
V51_CTRL_ID_RE_PROVISIONING_STARTED = 0x04,
V51_CTRL_ID_CANNOT_RE_PROVISION = 0x05,
V51_CTRL_ID_REQUEST_VARIANT_AND_INTERFACE_ID = 0x06,
V51_CTRL_ID_VARIANT_AND_INTERFACE_ID = 0x07,
V51_CTRL_ID_BLOCKING_STARTED = 0x08,
V51_CTRL_ID_RESTART_REQUEST = 0x10,
V51_CTRL_ID_RESTART_COMPLETE = 0x11,
};
extern const struct value_string v51_ctrl_func_id_str[];
/* 13.4.7.9 Cause */
enum v51_cause_type {
V51_CTRL_CAUSE_T_RESP_TO_STATUS_ENQ = 0x00,
V51_CTRL_CAUSE_T_L3_ADDRESS_ERROR = 0x03,
V51_CTRL_CAUSE_T_MSG_TYPE_UNRECOGNIZED = 0x04,
V51_CTRL_CAUSE_T_OUT_OF_SEQUENCE_IE = 0x05,
V51_CTRL_CAUSE_T_REPEATED_OPT_IE = 0x06,
V51_CTRL_CAUSE_T_MAND_IE_MISSING = 0x07,
V51_CTRL_CAUSE_T_UNRECOGNIZED_IE = 0x08,
V51_CTRL_CAUSE_T_MAND_IE_CONTENT_ERROR = 0x09,
V51_CTRL_CAUSE_T_OPT_IE_CONTENT_ERROR = 0x0a,
V51_CTRL_CAUSE_T_MSG_INCOMP_PATH_STATE = 0x0b,
V51_CTRL_CAUSE_T_REPEATED_MAND_IE = 0x0c,
V51_CTRL_CAUSE_T_TOO_MANY_IE = 0x0d,
};
extern const struct value_string v51_cause_type_str[];
const struct osmo_tlv_prot_def v51_ctrl_msg_tlv;
/* 16.3.2.2 Table 22/G.965 */
enum v52_link_ctrl_func {
V52_LCP_FE_IDReq = 0,
V52_LCP_FE_IDAck = 1,
V52_LCP_FE_IDRel = 2,
V52_LCP_FE_IDRej = 3,
V52_LCP_FE_301_302_LINK_UNBLOCK = 4,
V52_LCP_FE_303_304_LINK_BLOCK = 5,
V52_LCP_FE_305_DEF_LINK_BLOCK_REQ = 6,
V52_LCP_FE_306_NON_DEF_LINK_BLOCK_REQ = 7,
};