diff --git a/src/lapv5.c b/src/lapv5.c index e95ff6b..5e54c59 100644 --- a/src/lapv5.c +++ b/src/lapv5.c @@ -35,7 +35,9 @@ #include "v5x_internal.h" #include "v5x_protocol.h" +#include "v5x_le_port_fsm.h" #include "lapv5.h" +#include "layer1.h" #include "logging.h" #define LAPD_ADDR1(sapi, cr) ((((sapi) & 0x3f) << 2) | (((cr) & 0x1) << 1)) @@ -132,7 +134,7 @@ static struct lapv5_sap *lapv5_sap_alloc(struct lapv5_instance *li, uint16_t v5d if (!sap) return NULL; - LOGP(DLLAPD, LOGL_NOTICE, "(%s): LAPV5 Allocating SAP for V5_DLADDR=%u (dl=%p, sap=%p)\n", + LOGP(DLLAPD, LOGL_DEBUG, "(%s): LAPV5 Allocating SAP for V5_DLADDR=%u (dl=%p, sap=%p)\n", name, v5dladdr, &sap->dl, sap); sap->li = li; @@ -141,7 +143,7 @@ static struct lapv5_sap *lapv5_sap_alloc(struct lapv5_instance *li, uint16_t v5d profile = &li->profile; k = profile->k[0]; - LOGP(DLLAPD, LOGL_NOTICE, "(%s): k=%d N200=%d N201=%d T200=%d.%d T203=%d.%d\n", + LOGP(DLLAPD, LOGL_DEBUG, "(%s): k=%d N200=%d N201=%d T200=%d.%d T203=%d.%d\n", name, k, profile->n200, profile->n201, profile->t200_sec, profile->t200_usec, profile->t203_sec, profile->t203_usec); lapd_dl_init2(dl, k, 128, profile->n201, name); @@ -167,7 +169,7 @@ static struct lapv5_sap *lapv5_sap_alloc(struct lapv5_instance *li, uint16_t v5d /* Free SAP instance, including the datalink */ static void lapv5_sap_free(struct lapv5_sap *sap) { - LOGSAP(sap, LOGL_NOTICE, "LAPV5 Freeing SAP for DLADDR=%u (dl=%p, sap=%p)\n", sap->dladdr, &sap->dl, sap); + LOGSAP(sap, LOGL_DEBUG, "LAPV5 Freeing SAP for DLADDR=%u (dl=%p, sap=%p)\n", sap->dladdr, &sap->dl, sap); /* free datalink structures and timers */ lapd_dl_exit(&sap->dl); @@ -269,7 +271,7 @@ int lapv5_ph_data_ind(struct lapv5_instance *li, struct msgb *msg, int *error) return lapd_ph_data_ind(msg, &lctx); } -/* Start a (user-side) SAP for the specified TEI/SAPI on the LAPD instance */ +/* Start a (LE-side) SAP for the specified TEI/SAPI on the LAPD instance */ int lapv5_dl_est_req(struct lapv5_instance *li, uint16_t dladdr) { struct lapv5_sap *sap; @@ -284,18 +286,19 @@ int lapv5_dl_est_req(struct lapv5_instance *li, uint16_t dladdr) if (!sap) return -ENOMEM; - LOGSAP(sap, LOGL_NOTICE, "LAPV5 DL-ESTABLISH request DLADDR=%u\n", dladdr); + LOGSAP(sap, LOGL_DEBUG, "LAPV5 DL-ESTABLISH request DLADDR=%u\n", dladdr); /* prepare prim */ msg = msgb_alloc_headroom(DLSAP_MSGB_SIZE, DLSAP_MSGB_HEADROOM, "DL EST"); msg->l3h = msg->data; + memset(&dp, 0, sizeof(dp)); osmo_prim_init(&dp.oph, 0, PRIM_DL_EST, PRIM_OP_REQUEST, msg); /* send to L2 */ return lapd_recv_dlsap(&dp, &sap->dl.lctx); } -/* Stop a (user-side) SAP for the specified TEI/SAPI on the LAPD instance */ +/* Stop a (LE-side) SAP for the specified TEI/SAPI on the LAPD instance */ int lapv5_dl_rel_req(struct lapv5_instance *li, uint16_t dladdr) { struct lapv5_sap *sap; @@ -306,11 +309,12 @@ int lapv5_dl_rel_req(struct lapv5_instance *li, uint16_t dladdr) if (!sap) return -ENODEV; - LOGSAP(sap, LOGL_NOTICE, "LAPV5 DL-RELEASE request DLADDR=%u\n", dladdr); + LOGSAP(sap, LOGL_DEBUG, "LAPV5 DL-RELEASE request DLADDR=%u\n", dladdr); /* prepare prim */ msg = msgb_alloc_headroom(DLSAP_MSGB_SIZE, DLSAP_MSGB_HEADROOM, "DL REL"); msg->l3h = msg->data; + memset(&dp, 0, sizeof(dp)); osmo_prim_init(&dp.oph, 0, PRIM_DL_REL, PRIM_OP_REQUEST, msg); /* send to L2 */ @@ -325,13 +329,14 @@ int lapv5_dl_data_req(struct lapv5_instance *li, uint16_t dladdr, struct msgb *m sap = lapv5_sap_find(li, dladdr); if (!sap) { - LOGLI(li, LOGL_INFO, "LAPV5 Tx on unknown DLADDR=%u\n", dladdr); + LOGLI(li, LOGL_NOTICE, "LAPV5 Tx on unknown DLADDR=%u\n", dladdr); msgb_free(msg); return -EINVAL; } /* prepare prim */ msg->l3h = msg->data; + memset(&dp, 0, sizeof(dp)); osmo_prim_init(&dp.oph, 0, PRIM_DL_DATA, PRIM_OP_REQUEST, msg); /* send to L2 */ @@ -395,10 +400,10 @@ static int send_dlsap(struct osmo_dlsap_prim *dp, struct lapd_msg_ctx *lctx) switch (dp->oph.primitive) { case PRIM_DL_EST: - LOGDL(dl, LOGL_NOTICE, "LAPD DL-ESTABLISH %s DLADDR=%u\n", op, dladdr); + LOGDL(dl, LOGL_DEBUG, "LAPD DL-ESTABLISH %s DLADDR=%u\n", op, dladdr); break; case PRIM_DL_REL: - LOGDL(dl, LOGL_NOTICE, "LAPD DL-RELEASE %s DLADDR=%u\n", op, dladdr); + LOGDL(dl, LOGL_DEBUG, "LAPD DL-RELEASE %s DLADDR=%u\n", op, dladdr); lapv5_sap_free(sap); /* note: sap and dl is now gone, don't use it anymore */ break; @@ -499,27 +504,25 @@ int lapv5ef_rx(struct v5x_link *link, struct msgb *msg) case V5X_DLADDR_PSTN: /* hand-over to LAPD-DL instance for PSTN */ li = link->interface->pstn.li; - /* TODO */ break; case V5X_DLADDR_CTRL: /* hand-over to LAPD-DL instance for CTRL */ - /* TODO */ li = link->interface->control.li; break; case V52_DLADDR_BCC: + /* hand-over to LAPD-DL instance for BCC */ li = link->interface->bcc.li; - /* TOOD: implement V5.2 */ - msgb_free(msg); break; case V52_DLADDR_PROTECTION: - li = link->interface->protection[0].li; - /* TOOD: implement V5.2 */ - msgb_free(msg); + /* hand-over to LAPD-DL instance for PROTECTION */ + if (link == link->interface->primary_link) + li = link->interface->protection.li[0]; + if (link == link->interface->secondary_link) + li = link->interface->protection.li[1]; break; case V52_DLADDR_LCP: + /* hand-over to LAPD-DL instance for LCP */ li = link->interface->lcp.li; - /* TOOD: implement V5.2 */ - msgb_free(msg); break; default: if (efaddr >= 8176) { @@ -535,6 +538,11 @@ int lapv5ef_rx(struct v5x_link *link, struct msgb *msg) msgb_free(msg); return -EINVAL; } + if (!v5x_le_port_isdn_is_operational(v5up->port_fi)) { + LOGP(DV5EF, LOGL_NOTICE, "Dropping D-channel (AN->LE) message of non-operational ISDN port for EFaddr %d.\n", efaddr); + msgb_free(msg); + return -EIO; + } LOGP(DV5EF, LOGL_DEBUG, "Recevied frame for EFaddr %d: %s\n", efaddr, osmo_hexdump(msg->data, msg->len)); ph_socket_tx_msg(&v5up->ph_socket, 3, PH_PRIM_DATA_IND, msg->data, msg->len); msgb_free(msg); @@ -556,13 +564,18 @@ int lapv5ef_tx(struct v5x_user_port *v5up, struct msgb *msg) { uint16_t efaddr = v5up->nr, efaddr_enc; + if (!v5x_le_port_isdn_is_operational(v5up->port_fi)) { + LOGP(DV5EF, LOGL_NOTICE, "Dropping D-channel (LE->AN) message of non-operational ISDN port for EFaddr %d.\n", efaddr); + msgb_free(msg); + return -EIO; + } /* relay function for LAPD of user ports */ LOGP(DV5EF, LOGL_DEBUG, "Sending frame for EFaddr %d: %s\n", efaddr, osmo_hexdump(msg->data, msg->len)); msg->l2h = msgb_push(msg, 2); efaddr_enc = v5x_l3_addr_enc(efaddr, 1); msg->l2h[0] = efaddr_enc >> 8; msg->l2h[1] = efaddr_enc; - ph_data_req_hack(msg, NULL); + ph_data_req_hdlc(msg, v5up->interface); return 0; } diff --git a/src/lapv5.h b/src/lapv5.h index 48a6cbd..e512e04 100644 --- a/src/lapv5.h +++ b/src/lapv5.h @@ -32,6 +32,8 @@ struct lapv5_instance *lapv5_instance_alloc(int network_side, int (*ph_data_req_cb)(struct msgb *msg, void *cbdata), void *ph_data_req_cbdata, int (*dl_receive_cb)(struct osmo_dlsap_prim *odp, uint16_t dladdr, void *rx_cbdata), void *dl_receive_cbdata, const struct lapd_profile *profile, const char *name); +void lapv5_instance_set_profile(struct lapv5_instance *li, const struct lapd_profile *profile); +void lapv5_instance_free(struct lapv5_instance *li); int lapv5ef_rx(struct v5x_link *link, struct msgb *msg); int lapv5ef_tx(struct v5x_user_port *v5up, struct msgb *msg);