diff --git a/Makefile b/Makefile index ad4e2a0..828de0c 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ CFLAGS=-Wall -g -DPACKAGE_VERSION=\"0.0\" %.o: %.c $(CC) $(CFLAGS) -o $@ -c $^ -I/usr/local/include/ -v5le: main.o logging.o v5x_data.o lapv5.o +v5le: main.o logging.o v5x_data.o lapv5.o v5x_protocol.o $(CC) -o $@ $^ $(LIBS) clean: diff --git a/v5x_protocol.c b/v5x_protocol.c index 1bab85c..9c0c024 100644 --- a/v5x_protocol.c +++ b/v5x_protocol.c @@ -20,64 +20,71 @@ * */ -#include +#include #include #include +#include -#include +#include #include #include +#include "logging.h" +#include "v5x_internal.h" #include "v5x_protocol.h" +#include "v51_le_ctrl.h" +#include "lapv5.h" -const struct tlv_definition v51_ctrl_tlv_def[] = { - /* single byte: PSTN / G.964 Table 17 */ - [V51_CTRL_IEI_PULSE_NOTIFICATION] = TLV_TYPE_SINGLE_TV, - [V51_CTLR_IEI_LINE_NOTIFICATION] = TLV_TYPE_SINGLE_TV, - [V51_CTLR_IEI_STATE] = TLV_TYPE_SINGLE_TV, - [V51_CTLR_IEI_AUTONOMOUS_SIG_SEQ] = TLV_TYPE_SINGLE_TV, - [V51_CTLR_IEI_SEQUENCE_RESPONSE] = TLV_TYPE_SINGLE_TV, - /* single byte: ISDN / G.964 Table 53 */ - [V51_CTRL_IEI_PERFORMANCE_GRADING] = TLV_TYPE_SINGLE_TV, - [V51_CTRL_IEI_REJECTION_CAUSE] = TLV_TYPE_SINGLE_TV, +const struct tlv_definition v51_ctrl_tlv_def = { + .def = { + /* single byte: PSTN / G.964 Table 17 */ + [V51_CTRL_IEI_PULSE_NOTIFICATION] = { TLV_TYPE_SINGLE_TV }, + [V51_CTRL_IEI_LINE_NOTIFICATION] = { TLV_TYPE_SINGLE_TV }, + [V51_CTRL_IEI_STATE] = { TLV_TYPE_SINGLE_TV }, + [V51_CTRL_IEI_AUTONOMOUS_SIG_SEQ] = { TLV_TYPE_SINGLE_TV }, + [V51_CTRL_IEI_SEQUENCE_RESPONSE] = { TLV_TYPE_SINGLE_TV }, + /* single byte: ISDN / G.964 Table 53 */ + [V51_CTRL_IEI_PERFORMANCE_GRADING] = { TLV_TYPE_SINGLE_TV }, + [V51_CTRL_IEI_REJECTION_CAUSE] = { TLV_TYPE_SINGLE_TV }, - /* variable length: PSTN / G.964 Table 17 */ - [V51_CTRL_IEI_SEQUENCE_NR] = TLV_TYPE_TLV, - [V51_CTRL_IEI_CADENCED_RINGING] = TLV_TYPE_TLV, - [V51_CTRL_IEI_PULSED_SIGNAL] = TLV_TYPE_TLV, - [V51_CTRL_IEI_STEADY_SIGNAL] = TLV_TYPE_TLV, - [V51_CTRL_IEI_DIGIT_SIGNAL] = TLV_TYPE_TLV, - [V51_CTRL_IEI_RECOGNITION_TIME] = TLV_TYPE_TLV, - [V51_CTRL_IEI_ENABLE_AUTONOMOUS_ACK] = TLV_TYPE_TLV, - [V51_CTRL_IEI_DISABLE_AUTONOMOUS_ACK] = TLV_TYPE_TLV, - [V51_CTRL_IEI_CAUSE] = TLV_TYPE_TLV, - [V51_CTRL_IEI_RESOURCE_UNAVAILABLE] = TLV_TYPE_TLV, - [V51_CTRL_IEI_ENABLE_METERING] = TLV_TYPE_TLV, - [V51_CTRL_IEI_METERING_REPORT] = TLV_TYPE_TLV, - [V51_CTRL_IEI_ATTENUATION] = TLV_TYPE_TLV, + /* variable length: PSTN / G.964 Table 17 */ + [V51_CTRL_IEI_SEQUENCE_NR] = { TLV_TYPE_TLV }, + [V51_CTRL_IEI_CADENCED_RINGING] = { TLV_TYPE_TLV }, + [V51_CTRL_IEI_PULSED_SIGNAL] = { TLV_TYPE_TLV }, + [V51_CTRL_IEI_STEADY_SIGNAL] = { TLV_TYPE_TLV }, + [V51_CTRL_IEI_DIGIT_SIGNAL] = { TLV_TYPE_TLV }, + [V51_CTRL_IEI_RECOGNITION_TIME] = { TLV_TYPE_TLV }, + [V51_CTRL_IEI_ENABLE_AUTONOMOUS_ACK] = { TLV_TYPE_TLV }, + [V51_CTRL_IEI_DISABLE_AUTONOMOUS_ACK] = { TLV_TYPE_TLV }, + [V51_CTRL_IEI_CAUSE] = { TLV_TYPE_TLV }, + [V51_CTRL_IEI_RESOURCE_UNAVAILABLE] = { TLV_TYPE_TLV }, + [V51_CTRL_IEI_ENABLE_METERING] = { TLV_TYPE_TLV }, + [V51_CTRL_IEI_METERING_REPORT] = { TLV_TYPE_TLV }, + [V51_CTRL_IEI_ATTENUATION] = { TLV_TYPE_TLV }, - /* variable length: ISDN / G.964 Table 53 */ - [V51_CTRL_IEI_CTRL_F_ELEMENT] = TLV_TYPE_TLV, - [V51_CTRL_IEI_CTRL_F_ID] = TLV_TYPE_TLV, - [V51_CTRL_IEI_VARIANT] = TLV_TYPE_TLV, - [V51_CTRL_IEI_INTERFACE_ID] = TLV_TYPE_TLV, + /* variable length: ISDN / G.964 Table 53 */ + [V51_CTRL_IEI_CTRL_F_ELEMENT] = { TLV_TYPE_TLV }, + [V51_CTRL_IEI_CTRL_F_ID] = { TLV_TYPE_TLV }, + [V51_CTRL_IEI_VARIANT] = { TLV_TYPE_TLV }, + [V51_CTRL_IEI_INTERFACE_ID] = { TLV_TYPE_TLV }, - /* variable length: LCP / G.965 Table FIXME */ - [V52_CTRL_IEI_LCP_LINK_CTRL_FUNCTION] = TLV_TYPE_TLV, - /* variable length: BCC */ - [V52_CTRL_IEI_BCC_USER_PORT_ID] = TLV_TYPE_TLV, - [V52_CTRL_IEI_BCC_ISDN_PORT_TS_ID] = TLV_TYPE_TLV, - [V52_CTRL_IEI_BCC_V5_TS_ID] = TLV_TYPE_TLV, - [V52_CTRL_IEI_BCC_MULTI_TS_MAP] = TLV_TYPE_TLV, - [V52_CTRL_IEI_BCC_REJECT_CAUSE] = TLV_TYPE_TLV, - [V52_CTRL_IEI_BCC_PROTOCOL_ERROR_CAUSE] = TLV_TYPE_TLV, - [V52_CTRL_IEI_BCC_CONNECTION_INCOMPLETE] = TLV_TYPE_TLV, - [V52_CTRL_IEI_BCC_INFO_TRANSFER_CAPABILITY] = TLV_TYPE_TLV, - /* variable-length: Protection */ - [V52_CTRL_IEI_PP_SEQUENCE_NR] = TLV_TYPE_TLV, - [V52_CTRL_IEI_PP_PHYSICAL_C_CHAN_ID] = TLV_TYPE_TLV, - [V52_CTRL_IEI_PP_REJECTION_CAUSE] = TLV_TYPE_TLV, - [V52_CTRL_IEI_PP_PROTOCOL_ERROR_CAUSE] = TLV_TYPE_TLV, + /* variable length: LCP / G.965 Table FIXME */ + [V52_CTRL_IEI_LCP_LINK_CTRL_FUNCTION] = { TLV_TYPE_TLV }, + /* variable length: BCC */ + [V52_CTRL_IEI_BCC_USER_PORT_ID] = { TLV_TYPE_TLV }, + [V52_CTRL_IEI_BCC_ISDN_PORT_TS_ID] = { TLV_TYPE_TLV }, + [V52_CTRL_IEI_BCC_V5_TS_ID] = { TLV_TYPE_TLV }, + [V52_CTRL_IEI_BCC_MULTI_TS_MAP] = { TLV_TYPE_TLV }, + [V52_CTRL_IEI_BCC_REJECT_CAUSE] = { TLV_TYPE_TLV }, + [V52_CTRL_IEI_BCC_PROTOCOL_ERROR_CAUSE] = { TLV_TYPE_TLV }, + [V52_CTRL_IEI_BCC_CONNECTION_INCOMPLETE] = { TLV_TYPE_TLV }, + [V52_CTRL_IEI_BCC_INFO_TRANSFER_CAPABILITY] = { TLV_TYPE_TLV }, + /* variable-length: Protection */ + [V52_CTRL_IEI_PP_SEQUENCE_NR] = { TLV_TYPE_TLV }, + [V52_CTRL_IEI_PP_PHYSICAL_C_CHAN_ID] = { TLV_TYPE_TLV }, + [V52_CTRL_IEI_PP_REJECTION_CAUSE] = { TLV_TYPE_TLV }, + [V52_CTRL_IEI_PP_PROTOCOL_ERROR_CAUSE] = { TLV_TYPE_TLV }, + }, }; @@ -95,13 +102,14 @@ const struct value_string v51_ctrl_msg_typ_str[] = { { V51_CTRL_MSGT_PORT_CTRL_ACK, "PORT_CTRL_ACK" }, { V51_CTRL_MSGT_COMMON_CTRL, "COMMON_CTRL" }, { V51_CTRL_MSGT_COMMON_CTRL_ACK, "COMMON_CTRL_ACK" }, - { V52_CTRL_MSGT_SWITCH_OVER_REQ, "SWITCH_OVER_REQ" }, - { V52_CTRL_MSGT_SWITCH_OVER_COM, "SWITCH_OVER_COM" }, - { V52_CTRL_MSGT_OS_SWITCH_OVER_COM, "OS_SWITCH_OVER_COM" }, - { V52_CTRL_MSGT_SWITCH_OVER_ACK, "SWITCH_OVER_ACK" }, - { V52_CTRL_MSGT_SWITCH_OVER_REJECT, "SWITCH_OVER_REJECT" }, - { V52_CTRL_MSGT_RESET_SN_COM, "RESET_SN_COM" }, - { V52_CTRL_MSGT_RESET_SN_ACK, "RESET_SN_ACK" }, + { V52_CTRL_MSGT_PP_SWITCH_OVER_REQ, "SWITCH_OVER_REQ" }, + { V52_CTRL_MSGT_PP_SWITCH_OVER_COM, "SWITCH_OVER_COM" }, + { V52_CTRL_MSGT_PP_OS_SWITCH_OVER_COM, "OS_SWITCH_OVER_COM" }, + { V52_CTRL_MSGT_PP_SWITCH_OVER_ACK, "SWITCH_OVER_ACK" }, + { V52_CTRL_MSGT_PP_SWITCH_OVER_REJECT, "SWITCH_OVER_REJECT" }, + { V52_CTRL_MSGT_PP_PROTOCOL_ERROR, "PROTOCOL_ERROR" }, + { V52_CTRL_MSGT_PP_RESET_SN_COM, "RESET_SN_COM" }, + { V52_CTRL_MSGT_PP_RESET_SN_ACK, "RESET_SN_ACK" }, { V52_CTRL_MSGT_ALLOCATION, "ALLOCATION" }, { V52_CTRL_MSGT_ALLOCATION_COMPLETE, "ALLOCATION_COMPLETE" }, { V52_CTRL_MSGT_ALLOCATION_REJECT, "ALLOCATION_REJECT" }, @@ -111,19 +119,19 @@ const struct value_string v51_ctrl_msg_typ_str[] = { { V52_CTRL_MSGT_AUDIT, "AUDIT" }, { V52_CTRL_MSGT_AUDIT_COMPLETE, "AUDIT_COMPLETE" }, { V52_CTRL_MSGT_AN_FAULT, "AN_FAULT" }, - { V52_CTRL_MSGT_AN_FAULT_ACKNOWLEDGE "AN_FAULT_ACKNOWLEDGE" }, - { V52_CTRL_MSGT_PROTOCOL_ERROR "PROTOCOL_ERROR" }, - { V52_CTRL_MSGT_LINK_CTRL, "LINK_CTRL" }, - { V52_CTRL_MSGT_LINK_CTRL_ACK, "LINK_CTRL_ACK" }, + { V52_CTRL_MSGT_AN_FAULT_ACK, "AN_FAULT_ACKNOWLEDGE" }, + { V52_CTRL_MSGT_PROTOCOL_ERROR, "PROTOCOL_ERROR" }, + { V52_CTRL_MSGT_LCP_LINK_CTRL, "LINK_CTRL" }, + { V52_CTRL_MSGT_LCP_LINK_CTRL_ACK, "LINK_CTRL_ACK" }, { 0, NULL } }; const struct value_string v51_ctrl_iei_str[] = { { V51_CTRL_IEI_PULSE_NOTIFICATION, "PULSE_NOTIFICATION" }, - { V51_CTLR_IEI_LINE_NOTIFICATION, "LINE_NOTIFICATION" }, - { V51_CTLR_IEI_STATE, "STATE" }, - { V51_CTLR_IEI_AUTONOMOUS_SIG_SEQ, "AUTONOMOUS_SIG_SEQ" }, - { V51_CTLR_IEI_SEQUENCE_RESPONSE, "SEQUENCE_RESPONSE" }, + { V51_CTRL_IEI_LINE_NOTIFICATION, "LINE_NOTIFICATION" }, + { V51_CTRL_IEI_STATE, "STATE" }, + { V51_CTRL_IEI_AUTONOMOUS_SIG_SEQ, "AUTONOMOUS_SIG_SEQ" }, + { V51_CTRL_IEI_SEQUENCE_RESPONSE, "SEQUENCE_RESPONSE" }, { V51_CTRL_IEI_PERFORMANCE_GRADING, "PERFORMANCE_GRADING" }, { V51_CTRL_IEI_REJECTION_CAUSE, "REJECTION_CAUSE" }, { V51_CTRL_IEI_SEQUENCE_NR, "SEQUENCE_NR" }, @@ -144,7 +152,7 @@ const struct value_string v51_ctrl_iei_str[] = { { V51_CTRL_IEI_VARIANT, "VARIANT" }, { V51_CTRL_IEI_INTERFACE_ID, "INTERFACE_ID" }, { V52_CTRL_IEI_LCP_LINK_CTRL_FUNCTION, "LCP_LINK_CTRL_FUNCTION" }, - { V52_CTRL_IEI_BCC_USER_PORT_ID "BCC_USER_PORT_ID" }, + { V52_CTRL_IEI_BCC_USER_PORT_ID, "BCC_USER_PORT_ID" }, { V52_CTRL_IEI_BCC_ISDN_PORT_TS_ID, "BCC_ISDN_PORT_TS_ID" }, { V52_CTRL_IEI_BCC_V5_TS_ID, "BCC_V5_TS_ID" }, { V52_CTRL_IEI_BCC_MULTI_TS_MAP, "BCC_MULTI_TS_MAP" }, @@ -170,8 +178,8 @@ const struct value_string v51_ctrl_func_el_str[] = { { V51_CTRL_FE203_BLOCK, "FE203_BLOCK" }, { V51_CTRL_FE205_BLOCK_REQ, "FE205_BLOCK_REQ" }, { V51_CTRL_FE206_PERFORMANCE_GRADING, "FE206_PERFORMANCE_GRADING" }, - { V51_CTRL_FE206_D_CHANNEL_BLOCK, "FE206_D_CHANNEL_BLOCK" }, - { V51_CTRL_FE206_D_CHANNEL_UNBLOCK, "FE206_D_CHANNEL_UNBLOCK" } + { V51_CTRL_FE207_D_CHANNEL_BLOCK, "FE207_D_CHANNEL_BLOCK" }, + { V51_CTRL_FE208_D_CHANNEL_UNBLOCK, "FE208_D_CHANNEL_UNBLOCK" }, { 0, NULL } }; @@ -211,6 +219,7 @@ static const uint8_t signal_ack_mand_ies[] = { V51_CTRL_IEI_SEQUENCE_NR }; static const uint8_t status_mand_ies[] = { V51_CTRL_IEI_STATE, V51_CTRL_IEI_CAUSE }; static const uint8_t prot_par_mand_ies[] = { V51_CTRL_IEI_SEQUENCE_NR }; static const uint8_t port_ctrl_mand_ies[] = { V51_CTRL_IEI_CTRL_F_ELEMENT }; +static const uint8_t common_ctrl_mand_ies[] = { V51_CTRL_IEI_CTRL_F_ID }; static const uint8_t lcp_mand_ies[] = { V52_CTRL_IEI_LCP_LINK_CTRL_FUNCTION }; static const uint8_t alloc_mand_ies[] = { V52_CTRL_IEI_BCC_USER_PORT_ID }; static const uint8_t alloc_rej_mand_ies[] = { V52_CTRL_IEI_BCC_REJECT_CAUSE }; @@ -232,7 +241,7 @@ static const uint8_t pp_perr_mand_ies[] = { const struct osmo_tlv_prot_def v51_ctrl_msg_tlv = { .name = "V51_CTRL", - .tlv_def = v51_ctrl_tlv_def, + .tlv_def = &v51_ctrl_tlv_def, .msg_def = { /* G.964 Section 13.3 */ [V51_CTRL_MSGT_ESTABLISH] = MSG_DEF("ESTABLISH", NULL, 0), @@ -247,8 +256,8 @@ const struct osmo_tlv_prot_def v51_ctrl_msg_tlv = { /* G.964 Section 14.4 */ [V51_CTRL_MSGT_PORT_CTRL] = MSG_DEF("PORT_CTRL", port_ctrl_mand_ies, 0), [V51_CTRL_MSGT_PORT_CTRL_ACK] = MSG_DEF("PORT_CTRL_ACK", port_ctrl_mand_ies, 0), - [V51_CTRL_MSGT_COMMON_CTRL] = MSG_DEF("COMMON_CTRL", port_ctrl_mand_ies, 0), - [V51_CTRL_MSGT_COMMON_CTRL_ACK] = MSG_DEF("COMMON_CTRL_ACK", port_ctrl_mand_ies, 0), + [V51_CTRL_MSGT_COMMON_CTRL] = MSG_DEF("COMMON_CTRL", common_ctrl_mand_ies, 0), + [V51_CTRL_MSGT_COMMON_CTRL_ACK] = MSG_DEF("COMMON_CTRL_ACK", common_ctrl_mand_ies, 0), /* G.965 Section 16.3 LCP */ [V52_CTRL_MSGT_LCP_LINK_CTRL] = MSG_DEF("LINK_CONTROL", lcp_mand_ies, 0), [V52_CTRL_MSGT_LCP_LINK_CTRL_ACK] = MSG_DEF("LINK_CONTROL_ACK", lcp_mand_ies, 0), @@ -279,10 +288,10 @@ const struct osmo_tlv_prot_def v51_ctrl_msg_tlv = { .ie_def = { /* single byte, only upper nibble matches IEI */ [V51_CTRL_IEI_PULSE_NOTIFICATION] = { 0, "PULSE_NOTIFICATION" }, - [V51_CTLR_IEI_LINE_NOTIFICATION] = { 0, "LINE_NOTIFICATION" }, - [V51_CTLR_IEI_STATE] = { 0, "STATE" }, - [V51_CTLR_IEI_AUTONOMOUS_SIG_SEQ] = { 0, "AUTONOMOUS_SIG_SEQ" }, - [V51_CTLR_IEI_SEQUENCE_RESPONSE] = { 0, "SEQUENCE_RESPONSE" }, + [V51_CTRL_IEI_LINE_NOTIFICATION] = { 0, "LINE_NOTIFICATION" }, + [V51_CTRL_IEI_STATE] = { 0, "STATE" }, + [V51_CTRL_IEI_AUTONOMOUS_SIG_SEQ] = { 0, "AUTONOMOUS_SIG_SEQ" }, + [V51_CTRL_IEI_SEQUENCE_RESPONSE] = { 0, "SEQUENCE_RESPONSE" }, /* single byte: ISDN */ [V51_CTRL_IEI_PERFORMANCE_GRADING] = { 0, "PERFORMANCE_GRADING" }, [V51_CTRL_IEI_REJECTION_CAUSE] = { 0, "REJECTION_CAUSE" }, @@ -325,134 +334,237 @@ const struct osmo_tlv_prot_def v51_ctrl_msg_tlv = { .msgt_names = v51_ctrl_msg_typ_str, }; - -struct v5x_user_port *v5x_user_port_find(struct v5x_instance *v5i, uint16_t nr) +static int v51_rcv_pstn(struct v5x_user_port *v5up, uint16_t l3_addr, uint8_t msg_type, const struct tlv_parsed *tp) { - struct v5x_user_port *v5up; - - llist_for_each_entry(v5up, &v5i->user_ports, list) { - if (v5up->nr == l3_addr) - return v5up; - } - return NULL; + return 0; } - -static int v51_rcv_pstn(struct v5x_user_port *v5i, struct msgb *msg, const struct tlv_parsed *tp) +static int v52_rcv_pp(struct v5x_interface *v5if, uint16_t l3_addr, uint8_t msg_type, const struct tlv_parsed *tp) { - struct v51_l3_hdr *l3h = msgb_l3(msg); - - switch (l3h->msg_type) { - case V51_CTRL_MSGT_ESTABLISH: - case V51_CTRL_MSGT_ESTABLISH_ACK: - case V51_CTRL_MSGT_SIGNAL: - case V51_CTRL_MSGT_SIGNAL_ACK: - case V51_CTRL_MSGT_DISCONNECT: - case V51_CTRL_MSGT_DISCONNECT_ACK: - case V51_CTRL_MSGT_STATUS_ENQUIRY: - case V51_CTRL_MSGT_STATUS: - case V51_CTRL_MSGT_PROTOCOL_PARAMETER: - return -EINVAL; - } + return 0; } -static int v52_rcv_pp(struct v5x_instance *v5i, struct msgb *msg, const struct tlv_parsed *tp) +static int v52_rcv_bcc(struct v5x_interface *v5if, uint16_t l3_addr, uint8_t msg_type, const struct tlv_parsed *tp) { - struct v51_l3_hdr *l3h = msgb_l3(msg); + return 0; } -static int v52_rcv_bcc(struct v5x_instance *v5i, struct msgb *msg, const struct tlv_parsed *tp) +static int v52_rcv_lcp(struct v5x_interface *v5if, uint16_t l3_addr, uint8_t msg_type, const struct tlv_parsed *tp) { - struct v51_l3_hdr *l3h = msgb_l3(msg); -} - -static int v52_rcv_lcp(struct v5x_instance *v5i, struct msgb *msg, const struct tlv_parsed *tp) -{ - struct v51_l3_hdr *l3h = msgb_l3(msg); + return 0; } /* main entry point for received V5 messages */ -int v5x_rcv(struct v5x_instance *v5i, struct msgb *msg) +int v5x_rcv(struct osmo_dlsap_prim *odp, uint16_t dladdr, void *rx_cbdata) { - struct v51_l3_hdr *l3h = msgb_l3(msg); + struct v5x_interface *v5if = rx_cbdata; + struct msgb *msg = odp->oph.msg; + struct v51_l3_hdr *l3h; struct tlv_parsed tp; uint16_t l3_addr; + struct v5x_user_port *v5up; + int rc; + + // FIXME: + switch (odp->oph.primitive) { + case PRIM_DL_DATA: + LOGP(DV5, LOGL_DEBUG, "DL-DATA indication received\n"); + break; + case PRIM_DL_EST: + LOGP(DV5, LOGL_DEBUG, "DL-EST indication received\n"); + v51_start_ctrl(v5if->control.ctrl); + llist_for_each_entry(v5up, &v5if->user_ports, list) + v51_start_ctrl(v5up->ctrl); + goto out; + case PRIM_DL_REL: + LOGP(DV5, LOGL_DEBUG, "DL-REL indication received\n"); + v51_stop_ctrl(v5if->control.ctrl); + llist_for_each_entry(v5up, &v5if->user_ports, list) + v51_stop_ctrl(v5up->ctrl); + goto out; + default: + LOGP(DV5, LOGL_NOTICE, "Unhandled prim=%d\n", odp->oph.primitive); + rc = -EINVAL; + goto out; + } + + l3h = msgb_l3(msg); if (msgb_l3len(msg) < sizeof(*l3h)) { - LOGP(DV5, LOGL_ERROR, "Received short message (%u bytes < %u)\n", msgb_l3len(msg), sizeof(*l3h)); - return -EINVAL; + LOGP(DV5, LOGL_ERROR, "Received short message (%u bytes < %lu)\n", msgb_l3len(msg), sizeof(*l3h)); + rc = -EINVAL; + goto out; } if (l3h->pdisc != V51_CTRL_PDISC) { LOGP(DV5, LOGL_ERROR, "Received unsupported protocol discriminator 0x%02x\n", l3h->pdisc); - return -EINVAL; + rc = -EINVAL; + goto out; } - rc = osmo_tlv_prot_parse(v51_ctrl_msg_tlv, &tp, 1, l3h->msg_type, msgb_l3(msg) + sizeof(*l3h), + rc = osmo_tlv_prot_parse(&v51_ctrl_msg_tlv, &tp, 1, l3h->msg_type, msgb_l3(msg) + sizeof(*l3h), msgb_l3len(msg) - sizeof(*l3h), 0, 0, DV5, __func__); if (rc < 0) - return -EINVAL; + goto out; - l3_addr = v51_l3_addr_dec(l3h->l3_addr); + l3_addr = v51_l3_addr_dec(ntohs(l3h->l3_addr), NULL); + LOGP(DV5, LOGL_DEBUG, "Received message from AN with l3_addr = %d and msg_type %d\n", l3_addr, l3h->msg_type); - switch (l3h->msg_type) { - /* PSTN signaling protocol */ - case V51_CTRL_MSGT_ESTABLISH: - case V51_CTRL_MSGT_ESTABLISH_ACK: - case V51_CTRL_MSGT_SIGNAL: - case V51_CTRL_MSGT_SIGNAL_ACK: - case V51_CTRL_MSGT_DISCONNECT: - case V51_CTRL_MSGT_DISCONNECT_ACK: - case V51_CTRL_MSGT_STATUS_ENQUIRY: - case V51_CTRL_MSGT_STATUS: - case V51_CTRL_MSGT_PROTOCOL_PARAMETER: - /* look-up user port based on L3 addr? */ - v5up = v5x_user_port_find(v5i, l3_addr); - if (!v5up) - return -ENODEV; - rc = v51_rcv_pstn(v5up, msg, &tp); + switch (dladdr) { + case V51_DLADDR_PSTN: + /* PSTN signaling protocol */ + switch (l3h->msg_type) { + case V51_CTRL_MSGT_ESTABLISH: + case V51_CTRL_MSGT_ESTABLISH_ACK: + case V51_CTRL_MSGT_SIGNAL: + case V51_CTRL_MSGT_SIGNAL_ACK: + case V51_CTRL_MSGT_DISCONNECT: + case V51_CTRL_MSGT_DISCONNECT_ACK: + case V51_CTRL_MSGT_STATUS_ENQUIRY: + case V51_CTRL_MSGT_STATUS: + case V51_CTRL_MSGT_PROTOCOL_PARAMETER: + /* look-up user port based on L3 addr? */ + v5up = v5x_user_port_find(v5if, l3_addr); + if (!v5up) { + rc = -ENODEV; + break; + } + rc = v51_rcv_pstn(v5up, l3_addr, l3h->msg_type, &tp); + break; + default: + rc = -ENOTSUP; + LOGP(DV5, LOGL_ERROR, "Received unsupported PSTN message type %s\n", + osmo_tlv_prot_msg_name(&v51_ctrl_msg_tlv, l3h->msg_type)); + } break; - /* control protocol (Section 14 G.964) */ - case V51_CTRL_MSGT_PORT_CTRL: - case V51_CTRL_MSGT_PORT_CTRL_ACK: - case V51_CTRL_MSGT_COMMON_CTRL: - case V51_CTRL_MSGT_COMMON_CTRL_ACK: - rc = v51_rcv_ctrl(v5i, msg, &tp); + case V51_DLADDR_CTRL: + /* control protocol (Section 14 G.964) */ + switch (l3h->msg_type) { + case V51_CTRL_MSGT_PORT_CTRL: + case V51_CTRL_MSGT_PORT_CTRL_ACK: + case V51_CTRL_MSGT_COMMON_CTRL: + case V51_CTRL_MSGT_COMMON_CTRL_ACK: + rc = v51_rcv_ctrl(v5if, l3_addr, l3h->msg_type, &tp); + break; + default: + rc = -ENOTSUP; + LOGP(DV5, LOGL_ERROR, "Received unsupported CTRL message type %s\n", + osmo_tlv_prot_msg_name(&v51_ctrl_msg_tlv, l3h->msg_type)); + } break; - /* protection protocol (Section 18 G.965) */ - case V52_CTRL_MSGT_PP_SWITCH_OVER_REQ: - case V52_CTRL_MSGT_PP_SWITCH_OVER_COM: - case V52_CTRL_MSGT_PP_OS_SWITCH_OVER_COM: - case V52_CTRL_MSGT_PP_SWITCH_OVER_ACK: - case V52_CTRL_MSGT_PP_SWITCH_OVER_REJECT: - case V52_CTRL_MSGT_PP_PROTOCOL_ERROR: - case V52_CTRL_MSGT_PP_RESET_SN_COM: - case V52_CTRL_MSGT_PP_RESET_SN_ACK: - rc = v52_rcv_pp(v5i, msg, &tp); + case V52_DLADDR_BCC: + /* protection protocol (Section 18 G.965) */ + switch (l3h->msg_type) { + case V52_CTRL_MSGT_PP_SWITCH_OVER_REQ: + case V52_CTRL_MSGT_PP_SWITCH_OVER_COM: + case V52_CTRL_MSGT_PP_OS_SWITCH_OVER_COM: + case V52_CTRL_MSGT_PP_SWITCH_OVER_ACK: + case V52_CTRL_MSGT_PP_SWITCH_OVER_REJECT: + case V52_CTRL_MSGT_PP_PROTOCOL_ERROR: + case V52_CTRL_MSGT_PP_RESET_SN_COM: + case V52_CTRL_MSGT_PP_RESET_SN_ACK: + rc = v52_rcv_pp(v5if, l3_addr, l3h->msg_type, &tp); + break; + default: + rc = -ENOTSUP; + LOGP(DV5, LOGL_ERROR, "Received unsupported BCC message type %s\n", + osmo_tlv_prot_msg_name(&v51_ctrl_msg_tlv, l3h->msg_type)); + } break; - /* BCC protocol (Section 17 G.965) */ - case V52_CTRL_MSGT_ALLOCATION: - case V52_CTRL_MSGT_ALLOCATION_COMPLETE: - case V52_CTRL_MSGT_ALLOCATION_REJECT: - case V52_CTRL_MSGT_DE_ALLOCATION: - case V52_CTRL_MSGT_DE_ALLOCATION_COMPLETE: - case V52_CTRL_MSGT_DE_ALLOCATION_REJECT: - case V52_CTRL_MSGT_AUDIT: - case V52_CTRL_MSGT_AUDIT_COMPLETE: - case V52_CTRL_MSGT_AN_FAULT: - case V52_CTRL_MSGT_AN_FAULT_ACK: - case V52_CTRL_MSGT_PROTOCOL_ERROR: - rc = v52_rcv_bcc(v5i, msg, &tp); + case V52_DLADDR_PROTECTION: + /* BCC protocol (Section 17 G.965) */ + switch (l3h->msg_type) { + case V52_CTRL_MSGT_ALLOCATION: + case V52_CTRL_MSGT_ALLOCATION_COMPLETE: + case V52_CTRL_MSGT_ALLOCATION_REJECT: + case V52_CTRL_MSGT_DE_ALLOCATION: + case V52_CTRL_MSGT_DE_ALLOCATION_COMPLETE: + case V52_CTRL_MSGT_DE_ALLOCATION_REJECT: + case V52_CTRL_MSGT_AUDIT: + case V52_CTRL_MSGT_AUDIT_COMPLETE: + case V52_CTRL_MSGT_AN_FAULT: + case V52_CTRL_MSGT_AN_FAULT_ACK: + case V52_CTRL_MSGT_PROTOCOL_ERROR: + rc = v52_rcv_bcc(v5if, l3_addr, l3h->msg_type, &tp); + break; + default: + rc = -ENOTSUP; + LOGP(DV5, LOGL_ERROR, "Received unsupported PROTECTION message type %s\n", + osmo_tlv_prot_msg_name(&v51_ctrl_msg_tlv, l3h->msg_type)); + } break; - /* Link control protocol (Section 16 G.965) */ - case V52_CTRL_MSGT_LCP_LINK_CTRL: - case V52_CTRL_MSGT_LCP_LINK_CTRL_ACK: - rc = v52_rcv_lcp(v5i, msg, &tp); + case V52_DLADDR_LCP: + /* Link control protocol (Section 16 G.965) */ + switch (l3h->msg_type) { + case V52_CTRL_MSGT_LCP_LINK_CTRL: + case V52_CTRL_MSGT_LCP_LINK_CTRL_ACK: + rc = v52_rcv_lcp(v5if, l3_addr, l3h->msg_type, &tp); + break; + default: + rc = -ENOTSUP; + LOGP(DV5, LOGL_ERROR, "Received unsupported LCP message type %s\n", + osmo_tlv_prot_msg_name(&v51_ctrl_msg_tlv, l3h->msg_type)); + } break; default: + rc = -ENOTSUP; LOGP(DV5, LOGL_ERROR, "Received unsupported message type %s\n", - osmo_tlv_prot_msg_name(v51_ctrl_msg_tlv, l3h->msg_type); + osmo_tlv_prot_msg_name(&v51_ctrl_msg_tlv, l3h->msg_type)); } + +out: + if (msg) + msgb_free(msg); + + return rc; +} + +/* send V5 messages to DL instance, given by dladdr */ +int v5x_snd(struct v5x_interface *v5if, uint16_t dladdr, struct msgb *msg) +{ + struct lapv5_instance *li; + + switch (dladdr) { + case V51_DLADDR_PSTN: + li = v5if->pstn.li; + break; + case V51_DLADDR_CTRL: + li = v5if->control.li; + break; + case V52_DLADDR_BCC: + li = v5if->bcc.li; + break; + case V52_DLADDR_PROTECTION: + li = v5if->protection[0].li; + break; + case V52_DLADDR_LCP: + li = v5if->lcp.li; + break; + } + + if (!li) { + LOGP(DV5, LOGL_ERROR, "No instance for dladdr %d.\n", dladdr); + msgb_free(msg); + return -EINVAL; + } + + return lapv5_dl_data_req(li, dladdr, msg); +} + +// FIXME +#define V5_MSGB_SIZE 128 +#define V5_MSGB_HEADROOM 56 + +struct msgb *msgb_alloc_v5x(void) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(V5_MSGB_SIZE, V5_MSGB_HEADROOM, "V5 MSG"); + if (!msg) + return NULL; + msg->l3h = msg->data; + + return msg; } diff --git a/v5x_protocol.h b/v5x_protocol.h index 85f38cf..9a23ffd 100644 --- a/v5x_protocol.h +++ b/v5x_protocol.h @@ -134,10 +134,10 @@ extern const struct value_string v51_ctrl_msg_typ_str[]; 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, + V51_CTRL_IEI_LINE_NOTIFICATION = 0x80, + V51_CTRL_IEI_STATE = 0x90, + V51_CTRL_IEI_AUTONOMOUS_SIG_SEQ = 0xa0, + V51_CTRL_IEI_SEQUENCE_RESPONSE = 0xb0, /* single byte: ISDN */ V51_CTRL_IEI_PERFORMANCE_GRADING = 0xe0, V51_CTRL_IEI_REJECTION_CAUSE = 0xf0, @@ -180,7 +180,7 @@ enum v51_ctrl_iei { extern const struct value_string v51_ctrl_iei_str[]; -extern const struct tlv_definition v51_ctrl_tlv_def[]; +extern const struct tlv_definition v51_ctrl_tlv_def; extern const struct osmo_tlv_prot_def v51_ctrl_msg_tlv; @@ -237,7 +237,7 @@ enum v51_cause_type { extern const struct value_string v51_cause_type_str[]; -const struct osmo_tlv_prot_def v51_ctrl_msg_tlv; +//const struct osmo_tlv_prot_def v51_ctrl_msg_tlv; /* 16.3.2.2 Table 22/G.965 */ enum v52_link_ctrl_func { @@ -250,3 +250,7 @@ enum v52_link_ctrl_func { V52_LCP_FE_305_DEF_LINK_BLOCK_REQ = 6, V52_LCP_FE_306_NON_DEF_LINK_BLOCK_REQ = 7, }; + +int v5x_rcv(struct osmo_dlsap_prim *odp, uint16_t dladdr, void *rx_cbdata); +int v5x_snd(struct v5x_interface *v5if, uint16_t dladdr, struct msgb *msg); +struct msgb *msgb_alloc_v5x(void);