aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2017-03-15 18:03:42 +0100
committerHarald Welte <laforge@gnumonks.org>2017-03-15 21:05:50 +0100
commit24f2f694a3be96155c07baea7f493088fc1d1b24 (patch)
tree9125f97a2118497c6c764960844f8b662c05e2c7
parentfab15163721616e44a60c1342cda32d4e9d02762 (diff)
Add support for SGSN role via IFLA_GTP_ROLE
This patch corresponds to a Linux kernel patch extending the kernel GTP to also cover the SGSN role, not just the GGSN role. In order to keep the API/behavior compatible, gtp_dev_create() will continue to create GGSN-side tunnels, while a new gtp_dev_create_sgsn() is introduced to create SGSN-side tunnels. Signed-off-by: Harald Welte <laforge@gnumonks.org>
-rw-r--r--include/libgtpnl/gtpnl.h1
-rw-r--r--include/linux/if_link.h7
-rw-r--r--src/gtp-rtnl.c16
-rw-r--r--src/libgtpnl.map1
-rw-r--r--tools/gtp-link.c12
5 files changed, 33 insertions, 4 deletions
diff --git a/include/libgtpnl/gtpnl.h b/include/libgtpnl/gtpnl.h
index 49ba03d..33bb275 100644
--- a/include/libgtpnl/gtpnl.h
+++ b/include/libgtpnl/gtpnl.h
@@ -17,6 +17,7 @@ int genl_lookup_family(struct mnl_socket *nl, const char *family);
struct in_addr;
int gtp_dev_create(int dest_ns, const char *gtp_ifname, int fd0, int fd1);
+int gtp_dev_create_sgsn(int dest_ns, const char *gtp_ifname, int fd0, int fd1);
int gtp_dev_config(const char *iface, struct in_addr *net, uint32_t prefix);
int gtp_dev_destroy(const char *gtp_ifname);
diff --git a/include/linux/if_link.h b/include/linux/if_link.h
index a3f53c9..c66ebbd 100644
--- a/include/linux/if_link.h
+++ b/include/linux/if_link.h
@@ -518,11 +518,18 @@ enum {
#define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1)
/* GTP section */
+
+enum ifla_gtp_role {
+ GTP_ROLE_GGSN = 0,
+ GTP_ROLE_SGSN,
+};
+
enum {
IFLA_GTP_UNSPEC,
IFLA_GTP_FD0,
IFLA_GTP_FD1,
IFLA_GTP_PDP_HASHSIZE,
+ IFLA_GTP_ROLE,
__IFLA_GTP_MAX,
};
#define IFLA_GTP_MAX (__IFLA_GTP_MAX - 1)
diff --git a/src/gtp-rtnl.c b/src/gtp-rtnl.c
index 6bfec65..1dfd125 100644
--- a/src/gtp-rtnl.c
+++ b/src/gtp-rtnl.c
@@ -105,7 +105,8 @@ static int gtp_dev_talk(struct nlmsghdr *nlh, uint32_t seq)
return ret;
}
-int gtp_dev_create(int dest_ns, const char *gtp_ifname, int fd0, int fd1)
+static int _gtp_dev_create(int dest_ns, const char *gtp_ifname, int fd0,
+ int fd1, enum ifla_gtp_role role)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
@@ -129,13 +130,26 @@ int gtp_dev_create(int dest_ns, const char *gtp_ifname, int fd0, int fd1)
mnl_attr_put_u32(nlh, IFLA_GTP_FD0, fd0);
mnl_attr_put_u32(nlh, IFLA_GTP_FD1, fd1);
mnl_attr_put_u32(nlh, IFLA_GTP_PDP_HASHSIZE, 131072);
+ if (role != GTP_ROLE_GGSN)
+ mnl_attr_put_u32(nlh, IFLA_GTP_ROLE, role);
mnl_attr_nest_end(nlh, nest2);
mnl_attr_nest_end(nlh, nest);
return gtp_dev_talk(nlh, seq);
}
+
+int gtp_dev_create(int dest_ns, const char *gtp_ifname, int fd0, int fd1)
+{
+ return _gtp_dev_create(dest_ns, gtp_ifname, fd0, fd1, GTP_ROLE_GGSN);
+}
EXPORT_SYMBOL(gtp_dev_create);
+int gtp_dev_create_sgsn(int dest_ns, const char *gtp_ifname, int fd0, int fd1)
+{
+ return _gtp_dev_create(dest_ns, gtp_ifname, fd0, fd1, GTP_ROLE_SGSN);
+}
+EXPORT_SYMBOL(gtp_dev_create_sgsn);
+
int gtp_dev_destroy(const char *gtp_ifname)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
diff --git a/src/libgtpnl.map b/src/libgtpnl.map
index 9ca83c7..9ce465d 100644
--- a/src/libgtpnl.map
+++ b/src/libgtpnl.map
@@ -6,6 +6,7 @@ global:
genl_lookup_family;
gtp_dev_create;
+ gtp_dev_create_sgsn;
gtp_dev_config;
gtp_dev_destroy;
diff --git a/tools/gtp-link.c b/tools/gtp-link.c
index 97dfa45..8367c6e 100644
--- a/tools/gtp-link.c
+++ b/tools/gtp-link.c
@@ -43,9 +43,9 @@
int main(int argc, char *argv[])
{
char buf[MNL_SOCKET_BUFFER_SIZE];
- int ret;
+ int ret, sgsn_mode = 0;
- if (argc != 3) {
+ if (argc < 3) {
printf("Usage: %s <add|del> <device>\n", argv[0]);
exit(EXIT_FAILURE);
}
@@ -58,6 +58,9 @@ int main(int argc, char *argv[])
return 0;
}
+ if (argc > 3 && !strcmp(argv[3], "--sgsn"))
+ sgsn_mode = 1;
+
int fd1 = socket(AF_INET, SOCK_DGRAM, 0);
int fd2 = socket(AF_INET, SOCK_DGRAM, 0);
struct sockaddr_in sockaddr_fd1 = {
@@ -86,7 +89,10 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
- ret = gtp_dev_create(-1, argv[2], fd1, fd2);
+ if (sgsn_mode)
+ ret = gtp_dev_create_sgsn(-1, argv[2], fd1, fd2);
+ else
+ ret = gtp_dev_create(-1, argv[2], fd1, fd2);
if (ret < 0) {
perror("cannot create GTP device\n");
exit(EXIT_FAILURE);