/** | |
* GGSN.java | |
* | |
* Core logic of GGSN | |
**/ | |
class PDPcontext { | |
public int nsapi; | |
public String imsi; | |
//public int uplinkDataTeid; | |
//public int downlinkDataTeid; | |
} | |
class GGSN extends StateMachine | |
{ | |
private Charging charging; | |
private CLI cli; | |
private NodeConfiguration nodeConfiguration; | |
private int uplinkData; | |
private int downlinkData; | |
private PDPcontext pdpContext; | |
public GGSN(Charging charging, CLI cli, NodeConfiguration nodeConfiguration) | |
{ | |
this.charging = charging; | |
this.cli = cli; | |
this.nodeConfiguration = nodeConfiguration; | |
uplinkData = 0; | |
downlinkData = 0; | |
// NB: In our simplified view (for now) we only handle a single context, | |
// but the model can be easily enhanced to handle multiple contexts. | |
pdpContext = new PDPcontext(); | |
} | |
private void createPDPcontext(CreatePDPcontext request) | |
{ | |
// Control incoming data values - Qtronic specific to | |
// control test data generated for test suite. | |
/** | |
* Snippet of how it may look with a more or less | |
* one-to-one mapping between model and GTPC data: | |
require request.imsi_digits != null; | |
require request.imsi_digits.length == IMSI_OCTETS; | |
for (int i = 0; i < request.imsi_digits.length; i++) | |
require request.imsi_digits[i] == imsi1[i]; | |
require request.teidDataI != null; | |
require request.teidDataI.length == TEID_OCTETS; | |
for (int i = 0; i < request.teidDataI.length; i++) | |
require request.teidDataI[i] == teid1[i]; | |
**/ | |
// Our simplified view on data | |
require request.imsi == "240001111231411"; | |
//require request.downlinkDataTeid == 1; | |
require request.nsapi == 5; | |
require request.apn == "apn1.com"; | |
// Handle request - in our simplified view we handle | |
// only one single PDP context. The state machine is | |
// laid out so that a createPDPcontext will always be | |
// done before any update, delete, or sending of payload. | |
pdpContext.imsi = request.imsi; | |
pdpContext.nsapi = request.nsapi; | |
//pdpContext.downlinkDataTeid = request.downlinkDataTeid; | |
//pdpContext.uplinkDataTeid = 3; | |
} | |
private void sendRadiusAuthRequest() | |
{ | |
RadiusAccessRequest request; | |
GiRadiusOut.send(request); | |
requirement "Radius/Authentication/Send Access Request"; | |
} | |
private void confirmCreatePDPcontext() | |
{ | |
// Send response back | |
CreatePDPresponse response; | |
response.causevalue = REQUEST_ACCEPTED; | |
//response.uplinkDataTeid = pdpContext.uplinkDataTeid; | |
GnOut.send(response); | |
requirement "PDP context/Confirm successful creation"; | |
} | |
private void updatePDPcontext(UpdatePDPcontext request) | |
{ | |
// TODO: what to do with update?? | |
// Currently it seems TTCN libraries take care of both update | |
// details and receiving the correct response, as well as doing | |
// the pass/fail verdict. | |
// We can have an "empty" update request in the model to just | |
// trigger a call to the existing library update function, or | |
// we can add more detail to the model and NOT use the existing | |
// library update function. | |
// 100114: we can handle the response to the update on the | |
// model level for understanding, but regard it as a NOP on | |
// the QtronicHarness level. | |
require request.nsapi == pdpContext.nsapi; | |
//require request.downlinkDataTeid == pdpContext.downlinkDataTeid; | |
// Send response | |
UpdatePDPresponse response; | |
response.causevalue = REQUEST_ACCEPTED; | |
GnOut.send(response); | |
requirement "PDP context/Confirm successful update"; | |
} | |
private void deletePDPcontext(DeletePDPcontext request) | |
{ | |
// Take care of request parameters | |
require request.nsapi == pdpContext.nsapi; | |
// Send response back | |
DeletePDPresponse response; | |
response.causevalue = REQUEST_ACCEPTED; | |
GnOut.send(response); | |
requirement "PDP context/Confirm successful deletion"; | |
} | |
// forwardGPDUtoGi() - when a GPDU is recieved on the Gn interface | |
// the payload should be forwarded to the Gi interface | |
private void forwardGPDUtoGi(GPDU pdu) | |
{ | |
//require pdu.header.teid == pdpContext.uplinkDataTeid; | |
// TODO: how much detail on model level? | |
uplinkData++; | |
charging.payload(pdu); | |
// Forward payload | |
UDPpdu udpPdu; | |
udpPdu.data = pdu.data; | |
GiOut.send(udpPdu); | |
} | |
// forwardUdpPduToGn() - when a UDP pdu is recieved on the Gi interface | |
// it should be forwarded/tunneled to the Gn interface | |
private void forwardUdpPduToGn(UDPpdu udpPdu) | |
{ | |
// Forward/tunnel payload | |
GPDU pdu; | |
//pdu.header.teid = pdpContext.downlinkDataTeid; | |
pdu.data = udpPdu.data; | |
GnOut.send(pdu); | |
// TODO: how much detail on model level? | |
downlinkData++; | |
charging.payload(pdu); | |
} | |
} | |
void main() | |
{ | |
NodeConfiguration nodeConfiguration = new NodeConfiguration(); | |
Charging charging = new Charging(); | |
CLI cli = new CLI(nodeConfiguration); | |
GGSN ggsn = new GGSN(charging, cli, nodeConfiguration); | |
ggsn.start("GGSN"); | |
} |