aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2010-05-03 12:28:12 +0200
committerHarald Welte <laforge@gnumonks.org>2010-05-04 07:20:44 +0200
commit10997d0b9bbc63a4480b4e95fb4312fc0401685b (patch)
tree3ee1ca1ad52f211c392aa5a2b9b326077191cdcf
parent86fda90d036e30615c2930073e964a11952c7c9f (diff)
[gprs] LLC: API to send XID responses to XID commands
-rw-r--r--openbsc/include/openbsc/gprs_llc.h10
-rw-r--r--openbsc/src/gprs_llc.c71
2 files changed, 67 insertions, 14 deletions
diff --git a/openbsc/include/openbsc/gprs_llc.h b/openbsc/include/openbsc/gprs_llc.h
index 2ed2d12ea..5a6682d80 100644
--- a/openbsc/include/openbsc/gprs_llc.h
+++ b/openbsc/include/openbsc/gprs_llc.h
@@ -15,6 +15,16 @@ enum gprs_llc_sapi {
GPRS_SAPI_SNDCP11 = 11,
};
+/* Section 6.4 Commands and Responses */
+enum gprs_llc_u_cmd {
+ GPRS_LLC_U_DM_RESP = 0x01,
+ GPRS_LLC_U_DISC_CMD = 0x04,
+ GPRS_LLC_U_UA_RESP = 0x06,
+ GPRS_LLC_U_SABM_CMD = 0x07,
+ GPRS_LLC_U_FRMR_RESP = 0x08,
+ GPRS_LLC_U_XID = 0x0b,
+ GPRS_LLC_U_NULL_CMD = 0x00,
+};
int gprs_llc_rcvmsg(struct msgb *msg, struct tlv_parsed *tv);
int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command);
diff --git a/openbsc/src/gprs_llc.c b/openbsc/src/gprs_llc.c
index 6d1563621..dffca5e21 100644
--- a/openbsc/src/gprs_llc.c
+++ b/openbsc/src/gprs_llc.c
@@ -142,19 +142,6 @@ static int gprs_llc_fcs(uint8_t *data, unsigned int len)
return fcs_calc;
}
-/* transmit a simple U frame */
-static int gprs_llc_tx_u()
-{
- struct msgb *msg = msgb_alloc(LLC_ALLOC_SIZE, "GPRS/LLC");
-
- if (!msg)
- return -ENOMEM;
-
-
-
- /* transmit the frame via BSSGP->NS->... */
-}
-
static void t200_expired(void *data)
{
struct gprs_llc_lle *lle = data;
@@ -192,6 +179,53 @@ static void t201_expired(void *data)
}
}
+int gprs_llc_tx_u(struct msgb *msg, uint8_t sapi, int command,
+ enum gprs_llc_u_cmd u_cmd, int pf_bit)
+{
+ uint8_t *fcs, *llch;
+ uint8_t addr, ctrl;
+ uint32_t fcs_calc;
+
+ /* Identifiers from UP: (TLLI, SAPI) + (BVCI, NSEI) */
+
+ /* Address Field */
+ addr = sapi & 0xf;
+ if (command)
+ addr |= 0x40;
+
+ /* 6.3 Figure 8 */
+ ctrl = 0xe0 | u_cmd;
+ if (pf_bit)
+ ctrl |= 0x10;
+
+ /* prepend LLC UI header */
+ llch = msgb_push(msg, 2);
+ llch[0] = addr;
+ llch[1] = ctrl;
+
+ /* append FCS to end of frame */
+ fcs = msgb_put(msg, 3);
+ fcs_calc = gprs_llc_fcs(llch, fcs - llch);
+ fcs[0] = fcs_calc & 0xff;
+ fcs[1] = (fcs_calc >> 8) & 0xff;
+ fcs[2] = (fcs_calc >> 16) & 0xff;
+
+ /* Identifiers passed down: (BVCI, NSEI) */
+
+ return gprs_bssgp_tx_dl_ud(msg);
+}
+
+/* Send XID response to LLE */
+static int gprs_llc_tx_xid(struct gprs_llc_lle *lle, struct msgb *msg)
+{
+ /* copy identifiers from LLE to ensure lower layers can route */
+ msgb_tlli(msg) = lle->tlli;
+ msgb_bvci(msg) = lle->bvci;
+ msgb_nsei(msg) = lle->nsei;
+
+ return gprs_llc_tx_u(msg, lle->sapi, 0, GPRS_LLC_U_XID, 1);
+}
+
/* Transmit a UI frame over the given SAPI */
int gprs_llc_tx_ui(struct msgb *msg, uint8_t sapi, int command)
{
@@ -257,6 +291,8 @@ static int gprs_llc_hdr_dump(struct gprs_llc_hdr_parsed *gph)
static int gprs_llc_hdr_rx(struct gprs_llc_hdr_parsed *gph,
struct gprs_llc_lle *lle)
{
+ struct msgb *resp;
+
switch (gph->cmd) {
case GPRS_LLC_SABM: /* Section 6.4.1.1 */
lle->v_sent = lle->v_ack = lle->v_recv = 0;
@@ -284,6 +320,9 @@ static int gprs_llc_hdr_rx(struct gprs_llc_hdr_parsed *gph,
case GPRS_LLC_FRMR: /* Section 6.4.1.5 */
break;
case GPRS_LLC_XID: /* Section 6.4.1.6 */
+ /* FIXME: implement XID negotiation */
+ resp = msgb_alloc_headroom(4096, 1024, "LLC_XID");
+ gprs_llc_tx_xid(lle, resp);
break;
}
@@ -449,7 +488,7 @@ int gprs_llc_rcvmsg(struct msgb *msg, struct tlv_parsed *tv)
struct bssgp_ud_hdr *udh = (struct bssgp_ud_hdr *) msgb_bssgph(msg);
struct gprs_llc_hdr *lh = msgb_llch(msg);
struct gprs_llc_hdr_parsed llhp;
- struct gprs_llc_entity *lle;
+ struct gprs_llc_lle *lle;
int rc = 0;
/* Identifiers from DOWN: NSEI, BVCI, TLLI */
@@ -465,6 +504,10 @@ int gprs_llc_rcvmsg(struct msgb *msg, struct tlv_parsed *tv)
if (!lle)
lle = lle_alloc(msgb_tlli(msg), llhp.sapi);
+ /* Update LLE's (BVCI, NSEI) tuple */
+ lle->bvci = msgb_bvci(msg);
+ lle->nsei = msgb_nsei(msg);
+
rc = gprs_llc_hdr_rx(&llhp, lle);
/* FIXME */