osmo-v5/src/v5x_protocol.h

316 lines
11 KiB
C

#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-2022 by Harald Welte <laforge@gnumonks.org>
* (C) 2022-2023 by Andreas Eversberg <jolly@eversberg.eu>
*/
/***********************************************************************/
/* protocol wire format */
/***********************************************************************/
/* Table 14/G.964 */
#define V5X_CTRL_PDISC 0x48
/* Table 1/G.965 + Table 1/G.964 */
#define V5X_DLADDR_PSTN 8176
#define V5X_DLADDR_CTRL 8177
#define V52_DLADDR_BCC 8178
#define V52_DLADDR_PROTECTION 8179
#define V52_DLADDR_LCP 8180
/* G.965 Section 13.1 */
struct v5x_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 v5x_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 v5x_l3_addr_dec(uint16_t in, bool *is_isdn)
{
/* extract two bytes */
uint8_t b1 = in >> 8;
uint8_t b2 = in & 0xff;
if (v5x_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 v5x_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 v5x_ctrl_msg_type {
/* 000xxxx: PSTN protocol message types */
V5X_CTRL_MSGT_ESTABLISH = 0x00,
V5X_CTRL_MSGT_ESTABLISH_ACK = 0x01,
V5X_CTRL_MSGT_SIGNAL = 0x02,
V5X_CTRL_MSGT_SIGNAL_ACK = 0x03,
V5X_CTRL_MSGT_DISCONNECT = 0x08,
V5X_CTRL_MSGT_DISCONNECT_COMPLETE = 0x09,
V5X_CTRL_MSGT_STATUS_ENQUIRY = 0x0c,
V5X_CTRL_MSGT_STATUS = 0x0d,
V5X_CTRL_MSGT_PROTOCOL_PARAMETER = 0x0e,
/* 0010xxx: Control protocol message types */
V5X_CTRL_MSGT_PORT_CTRL = 0x10,
V5X_CTRL_MSGT_PORT_CTRL_ACK = 0x11,
V5X_CTRL_MSGT_COMMON_CTRL = 0x12,
V5X_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 v5x_ctrl_msg_typ_str[];
/* Table 17 + 53/G.964 */
enum v5x_ctrl_iei {
/* single byte, only upper nibble matches IEI */
V5X_CTRL_IEI_PULSE_NOTIFICATION = 0xc0,
V5X_CTRL_IEI_LINE_INFORMATION = 0x80,
V5X_CTRL_IEI_STATE = 0x90,
V5X_CTRL_IEI_AUTONOMOUS_SIG_SEQ = 0xa0,
V5X_CTRL_IEI_SEQUENCE_RESPONSE = 0xb0,
/* single byte: ISDN */
V5X_CTRL_IEI_PERFORMANCE_GRADING = 0xe0,
V5X_CTRL_IEI_REJECTION_CAUSE = 0xf0,
/* variable length: PSTN */
V5X_CTRL_IEI_SEQUENCE_NR = 0x00,
V5X_CTRL_IEI_CADENCED_RINGING = 0x01,
V5X_CTRL_IEI_PULSED_SIGNAL = 0x02,
V5X_CTRL_IEI_STEADY_SIGNAL = 0x03,
V5X_CTRL_IEI_DIGIT_SIGNAL = 0x04,
V5X_CTRL_IEI_RECOGNITION_TIME = 0x10,
V5X_CTRL_IEI_ENABLE_AUTONOMOUS_ACK = 0x11,
V5X_CTRL_IEI_DISABLE_AUTONOMOUS_ACK = 0x12,
V5X_CTRL_IEI_CAUSE = 0x13,
V5X_CTRL_IEI_RESOURCE_UNAVAILABLE = 0x14,
V5X_CTRL_IEI_ENABLE_METERING = 0x32,
V5X_CTRL_IEI_METERING_REPORT = 0x33,
V5X_CTRL_IEI_ATTENUATION = 0x34,
/* variable length: ISDN */
V5X_CTRL_IEI_CTRL_F_ELEMENT = 0x20,
V5X_CTRL_IEI_CTRL_F_ID = 0x21,
V5X_CTRL_IEI_VARIANT = 0x22,
V5X_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 v5x_ctrl_iei_str[];
extern const struct tlv_definition v5x_ctrl_tlv_def;
extern const struct osmo_tlv_prot_def v5x_ctrl_msg_tlv;
/* 14.4.2.5.4 Table 56/G.964 - Coding of Control Function Element */
enum v5x_ctrl_func_el {
V5X_CTRL_FE101_ACTIVATE_ACCESS = 0x01,
V5X_CTRL_FE102_ACT_INIT_BY_USER = 0x02,
V5X_CTRL_FE103_DS_ACTIVATED = 0x03,
V5X_CTRL_FE104_ACCESS_ACTIVATED = 0x04,
V5X_CTRL_FE105_DEACTIVATE_ACCESS = 0x05,
V5X_CTRL_FE106_ACCESS_DEACTIVATED = 0x06,
V5X_CTRL_FE201_UNBLOCK = 0x11,
V5X_CTRL_FE203_BLOCK = 0x13,
V5X_CTRL_FE205_BLOCK_REQ = 0x15,
V5X_CTRL_FE206_PERFORMANCE_GRADING = 0x16,
V5X_CTRL_FE207_D_CHANNEL_BLOCK = 0x17,
V5X_CTRL_FE208_D_CHANNEL_UNBLOCK = 0x18,
};
extern const struct value_string v5x_ctrl_func_el_str[];
enum v5x_ctrl_func_id {
/* 14.4.2.5.5 Table 57/G.964 - Coding of Control Function ID */
V5X_CTRL_ID_VERIFY_RE_PROVISIONING = 0x00,
V5X_CTRL_ID_READY_FOR_RE_PROVISIONING = 0x01,
V5X_CTRL_ID_NOT_READY_FOR_RE_PROVISIONING = 0x02,
V5X_CTRL_ID_SWITCH_OVER_TO_NEW_VARIANT = 0x03,
V5X_CTRL_ID_RE_PROVISIONING_STARTED = 0x04,
V5X_CTRL_ID_CANNOT_RE_PROVISION = 0x05,
V5X_CTRL_ID_REQUEST_VARIANT_AND_INTERFACE_ID = 0x06,
V5X_CTRL_ID_VARIANT_AND_INTERFACE_ID = 0x07,
V5X_CTRL_ID_BLOCKING_STARTED = 0x08,
V5X_CTRL_ID_RESTART_REQUEST = 0x10,
V5X_CTRL_ID_RESTART_COMPLETE = 0x11,
/* 15.4.2 Table 9a/G.965 - Coding of Control Function ID */
V5X_CTRL_ID_UNBLK_ALL_REL_PSTN_ISDN_REQUEST = 0x12,
V5X_CTRL_ID_UNBLK_ALL_REL_PSTN_ISDN_ACCEPTED = 0x13,
V5X_CTRL_ID_UNBLK_ALL_REL_PSTN_ISDN_REJECTED = 0x14,
V5X_CTRL_ID_UNBLK_ALL_REL_PSTN_ISDN_COMPLETED = 0x15,
V5X_CTRL_ID_UNBLK_ALL_REL_PSTN_REQUEST = 0x16,
V5X_CTRL_ID_UNBLK_ALL_REL_PSTN_ACCEPTED = 0x17,
V5X_CTRL_ID_UNBLK_ALL_REL_PSTN_REJECTED = 0x18,
V5X_CTRL_ID_UNBLK_ALL_REL_PSTN_COMPLETED = 0x19,
V5X_CTRL_ID_UNBLK_ALL_REL_ISDN_REQUEST = 0x1a,
V5X_CTRL_ID_UNBLK_ALL_REL_ISDN_ACCEPTED = 0x1b,
V5X_CTRL_ID_UNBLK_ALL_REL_ISDN_REJECTED = 0x1c,
V5X_CTRL_ID_UNBLK_ALL_REL_ISDN_COMPLETED = 0x1d,
V5X_CTRL_ID_BLK_ALL_PSTN_REQUEST = 0x1e,
V5X_CTRL_ID_BLK_ALL_PSTN_ACCEPTED = 0x1f,
V5X_CTRL_ID_BLK_ALL_PSTN_REJECTED = 0x20,
V5X_CTRL_ID_BLK_ALL_PSTN_COMPLETED = 0x21,
V5X_CTRL_ID_BLK_ALL_ISDN_REQUEST = 0x22,
V5X_CTRL_ID_BLK_ALL_ISDN_ACCEPTED = 0x23,
V5X_CTRL_ID_BLK_ALL_ISDN_REJECTED = 0x24,
V5X_CTRL_ID_BLK_ALL_ISDN_COMPLETED = 0x25,
};
extern const struct value_string v5x_ctrl_func_id_str[];
/* 13.4.7.9 Cause / 17.4.2.6 Table 43/G.965 / 18.5.5 Table 62/G.965 */
enum v5x_ctrl_cause_type {
V5X_CAUSE_T_RESP_TO_STATUS_ENQ = 0x00,
V5X_CAUSE_T_PROTOCOL_DISC_ERROR = 0x01,
V5X_CAUSE_T_L3_ADDRESS_ERROR = 0x03,
V5X_CAUSE_T_MSG_TYPE_UNRECOGNIZED = 0x04,
V5X_CAUSE_T_OUT_OF_SEQUENCE_IE = 0x05,
V5X_CAUSE_T_REPEATED_OPT_IE = 0x06,
V5X_CAUSE_T_MAND_IE_MISSING = 0x07,
V5X_CAUSE_T_UNRECOGNIZED_IE = 0x08,
V5X_CAUSE_T_MAND_IE_CONTENT_ERROR = 0x09,
V5X_CAUSE_T_OPT_IE_CONTENT_ERROR = 0x0a,
V5X_CAUSE_T_MSG_INCOMP_STATE = 0x0b,
V5X_CAUSE_T_REPEATED_MAND_IE = 0x0c,
V5X_CAUSE_T_TOO_MANY_IE = 0x0d,
V5X_CAUSE_T_REF_NR_CODING_ERROR = 0x0f,
};
/* 17.4.2.5 Table 41/G.965 - Reject cause type */
enum v52_bcc_reject_cause_type {
V52_BCC_REJECT_CAUSE_T_UNSPECIFIED = 0x00,
V52_BCC_REJECT_CAUSE_T_ACCESS_NET_FAUL = 0x01,
V52_BCC_REJECT_CAUSE_T_ACCESS_NET_BLOCKED = 0x02,
V52_BCC_REJECT_CAUSE_T_CONN_PRESENT_PSTN = 0x03,
V52_BCC_REJECT_CAUSE_T_CONN_PRESENT_V5_TS = 0x04,
V52_BCC_REJECT_CAUSE_T_CONN_PRESENT_ISDN = 0x05,
V52_BCC_REJECT_CAUSE_T_USER_PORT_UNAVAILABLE = 0x06,
V52_BCC_REJECT_CAUSE_T_DEALLOC_INCOMPAT_DATA = 0x07,
V52_BCC_REJECT_CAUSE_T_DEALLOC_V5_TS_DATA = 0x08,
V52_BCC_REJECT_CAUSE_T_DEALLOC_PORT_DATA = 0x09,
V52_BCC_REJECT_CAUSE_T_DEALLOC_USER_TS_DATA = 0x0a,
V52_BCC_REJECT_CAUSE_T_USER_NOT_PROVISIONED = 0x0b,
V52_BCC_REJECT_CAUSE_T_INVALID_V5_TS_IDENT = 0x0c,
V52_BCC_REJECT_CAUSE_T_INVALID_V5_LINK_IDENT = 0x0d,
V52_BCC_REJECT_CAUSE_T_INVALID_USER_TS_IDENT = 0x0e,
V52_BCC_REJECT_CAUSE_T_V5_TS_USED_CCHANNEL = 0x0f,
V52_BCC_REJECT_CAUSE_T_V5_LINK_UNAVAILABLE = 0x10,
};
/* 18.5.4 Table 61/G.965 - Reject cause type */
enum v52_pp_reject_cause_type {
V52_PP_REJECT_CAUSE_T_NO_STANDBY_CC_AVAILABLE = 0x00,
V52_PP_REJECT_CAUSE_T_TARGET_CC_NOT_OPER = 0x01,
V52_PP_REJECT_CAUSE_T_TARGET_CC_NOT_PROV = 0x02,
V52_PP_REJECT_CAUSE_T_PROT_SWITCHING_IMPOSS = 0x03,
V52_PP_REJECT_CAUSE_T_PROT_GROUP_MISMATCH = 0x04,
V52_PP_REJECT_CAUSE_T_ALLOC_EXISTS_ALREADY = 0x05,
V52_PP_REJECT_CAUSE_T_TARGET_CC_ALREADY_CC = 0x06,
};
extern const struct value_string v5x_cause_type_str[];
extern const struct value_string v52_bcc_reject_cause_type_str[];
extern const struct value_string v52_pp_reject_cause_type_str[];
//extern 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,
};
int v5x_dl_rcv(struct osmo_dlsap_prim *odp, uint16_t dladdr, void *rx_cbdata);
int v5x_dl_snd(struct v5x_interface *v5if, uint16_t dladdr, struct msgb *msg);
struct msgb *msgb_alloc_v5x(void);