ns2: add support for frame relay
Add support for frame relay over dahdi hdlc device.
It's supporting lmi by q933 and supports both
SGSN and BSS.
Change-Id: Id3b49f93d33c271f77cd9c9db03cde6b727a4d30
diff --git a/src/gb/gprs_ns2_vty.c b/src/gb/gprs_ns2_vty.c
index 63331b9..4eb9d37 100644
--- a/src/gb/gprs_ns2_vty.c
+++ b/src/gb/gprs_ns2_vty.c
@@ -31,6 +31,7 @@
#include <stdint.h>
#include <arpa/inet.h>
+#include <net/if.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/byteswap.h>
@@ -42,6 +43,7 @@
#include <osmocom/core/sockaddr_str.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/socket.h>
+#include <osmocom/gprs/frame_relay.h>
#include <osmocom/gprs/gprs_ns2.h>
#include <osmocom/gsm/tlv.h>
#include <osmocom/vty/vty.h>
@@ -78,12 +80,19 @@
uint16_t nsvci;
uint16_t frdlci;
+ struct {
+ enum osmo_fr_role role;
+ } fr;
+
+ char netif[IF_NAMESIZE];
+
bool remote_end_is_sgsn;
bool configured;
};
static struct gprs_ns2_inst *vty_nsi = NULL;
static struct ns2_vty_priv priv;
+static struct osmo_fr_network *vty_fr_network = NULL;
/* FIXME: this should go to some common file as it is copied
* in vty_interface.c of the BSC */
@@ -223,6 +232,11 @@
vtyvc->nsei, vtyvc->frdlci,
VTY_NEWLINE);
break;
+ case GPRS_NS_LL_FR:
+ vty_out(vty, " nse %u fr %s dlci %u%s",
+ vtyvc->nsei, vtyvc->netif, vtyvc->frdlci,
+ VTY_NEWLINE);
+ break;
default:
break;
}
@@ -387,6 +401,44 @@
#define NSE_CMD_STR "Persistent NS Entity\n" "NS Entity ID (NSEI)\n"
+DEFUN(cfg_nse_fr, cfg_nse_fr_cmd,
+ "nse <0-65535> nsvci <0-65535> (fr|frnet) NETIF dlci <0-1023>",
+ NSE_CMD_STR
+ "NS Virtual Connection\n"
+ "NS Virtual Connection ID (NSVCI)\n"
+ "frame relay\n"
+ IFNAME_STR
+ "Data Link connection identifier\n"
+ "Data Link connection identifier\n"
+ )
+{
+ struct ns2_vty_vc *vtyvc;
+
+ uint16_t nsei = atoi(argv[0]);
+ uint16_t nsvci = atoi(argv[1]);
+ const char *role = argv[2];
+ const char *name = argv[3];
+ uint16_t dlci = atoi(argv[4]);
+
+ vtyvc = vtyvc_by_nsei(nsei, true);
+ if (!vtyvc) {
+ vty_out(vty, "Can not allocate space %s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (!strcmp(role, "fr"))
+ vtyvc->fr.role = FR_ROLE_USER_EQUIPMENT;
+ else if (!strcmp(role, "frnet"))
+ vtyvc->fr.role = FR_ROLE_NETWORK_EQUIPMENT;
+
+ osmo_strlcpy(vtyvc->netif, name, sizeof(vtyvc->netif));
+ vtyvc->frdlci = dlci;
+ vtyvc->nsvci = nsvci;
+ vtyvc->ll = GPRS_NS_LL_FR;
+
+ return CMD_SUCCESS;
+}
+
DEFUN(cfg_nse_nsvc, cfg_nse_nsvci_cmd,
"nse <0-65535> nsvci <0-65535>",
NSE_CMD_STR
@@ -453,13 +505,14 @@
}
DEFUN(cfg_nse_fr_dlci, cfg_nse_fr_dlci_cmd,
- "nse <0-65535> fr-dlci <16-1007>",
+ "nse <0-65535> nsvci <0-65535> fr-dlci <16-1007>",
NSE_CMD_STR
"Frame Relay DLCI\n"
"Frame Relay DLCI Number\n")
{
uint16_t nsei = atoi(argv[0]);
- uint16_t dlci = atoi(argv[1]);
+ uint16_t nsvci = atoi(argv[1]);
+ uint16_t dlci = atoi(argv[2]);
struct ns2_vty_vc *vtyvc;
vtyvc = vtyvc_by_nsei(nsei, true);
@@ -474,6 +527,7 @@
}
vtyvc->frdlci = dlci;
+ vtyvc->nsvci = nsvci;
return CMD_SUCCESS;
}
@@ -736,6 +790,7 @@
install_lib_element(CONFIG_NODE, &cfg_ns_cmd);
install_node(&ns_node, config_write_ns);
+ install_lib_element(L_NS_NODE, &cfg_nse_fr_cmd);
install_lib_element(L_NS_NODE, &cfg_nse_nsvci_cmd);
install_lib_element(L_NS_NODE, &cfg_nse_remoteip_cmd);
install_lib_element(L_NS_NODE, &cfg_nse_remoteport_cmd);
@@ -763,10 +818,11 @@
*/
int gprs_ns2_vty_create() {
struct ns2_vty_vc *vtyvc;
- struct gprs_ns2_vc_bind *bind;
+ struct gprs_ns2_vc_bind *bind, *fr;
struct gprs_ns2_nse *nse;
struct gprs_ns2_vc *nsvc;
struct osmo_sockaddr sockaddr;
+ int rc = 0;
if (!vty_nsi)
return -1;
@@ -787,18 +843,28 @@
/* create vcs */
llist_for_each_entry(vtyvc, &priv.vtyvc, list) {
- if (strlen(vtyvc->remote.ip) == 0) {
- /* Invalid IP for VC */
- continue;
- }
+ /* validate settings */
+ switch (vtyvc->ll) {
+ case GPRS_NS_LL_UDP:
+ if (strlen(vtyvc->remote.ip) == 0) {
+ /* Invalid IP for VC */
+ continue;
+ }
- if (!vtyvc->remote.port) {
- /* Invalid port for VC */
- continue;
- }
+ if (!vtyvc->remote.port) {
+ /* Invalid port for VC */
+ continue;
+ }
- if (osmo_sockaddr_str_to_sockaddr(&vtyvc->remote, &sockaddr.u.sas)) {
- /* Invalid sockaddr for VC */
+ if (osmo_sockaddr_str_to_sockaddr(&vtyvc->remote, &sockaddr.u.sas)) {
+ /* Invalid sockaddr for VC */
+ continue;
+ }
+ break;
+ case GPRS_NS_LL_FR:
+ break;
+ case GPRS_NS_LL_FR_GRE:
+ case GPRS_NS_LL_E1:
continue;
}
@@ -812,15 +878,46 @@
}
nse->persistent = true;
- nsvc = gprs_ns2_ip_connect(bind,
- &sockaddr,
- nse,
- vtyvc->nsvci);
- if (!nsvc) {
- /* Could not create NSVC, connect failed */
+ switch (vtyvc->ll) {
+ case GPRS_NS_LL_UDP:
+ nsvc = gprs_ns2_ip_connect(bind,
+ &sockaddr,
+ nse,
+ vtyvc->nsvci);
+ if (!nsvc) {
+ /* Could not create NSVC, connect failed */
+ continue;
+ }
+ nsvc->persistent = true;
+ break;
+ case GPRS_NS_LL_FR: {
+ if (vty_fr_network == NULL) {
+ /* TODO: add a switch for BSS/SGSN/gbproxy */
+ vty_fr_network = osmo_fr_network_alloc(vty_nsi);
+ }
+ fr = gprs_ns2_fr_bind_by_netif(
+ vty_nsi,
+ vtyvc->netif);
+ if (!fr) {
+ rc = gprs_ns2_fr_bind(vty_nsi, vtyvc->netif, vty_fr_network, vtyvc->fr.role, &fr);
+ if (rc < 0) {
+ LOGP(DLNS, LOGL_ERROR, "Can not create fr bind on device %s err: %d\n", vtyvc->netif, rc);
+ return rc;
+ }
+ }
+
+ nsvc = gprs_ns2_fr_connect(fr, vtyvc->nsei, vtyvc->nsvci, vtyvc->frdlci);
+ if (!nsvc) {
+ /* Could not create NSVC, connect failed */
+ continue;
+ }
+ nsvc->persistent = true;
+ break;
+ }
+ case GPRS_NS_LL_FR_GRE:
+ case GPRS_NS_LL_E1:
continue;
}
- nsvc->persistent = true;
}