#pragma once #include #include #include /* 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 * (C) 2022-2023 by Andreas Eversberg */ /***********************************************************************/ /* 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);